From 7d5175ea4d04cf6b333249f295caca9d811b6865 Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Sun, 27 Oct 2019 19:20:30 +0100
Subject: [PATCH 01/11] Unnesesary log
---
SUPLA/SAChannelBase+CoreDataClass.m | 3 ---
1 file changed, 3 deletions(-)
diff --git a/SUPLA/SAChannelBase+CoreDataClass.m b/SUPLA/SAChannelBase+CoreDataClass.m
index e13593d5..953f9fa0 100644
--- a/SUPLA/SAChannelBase+CoreDataClass.m
+++ b/SUPLA/SAChannelBase+CoreDataClass.m
@@ -349,9 +349,6 @@ - (UIImage*) getIconWithIndex:(short)idx {
UIImage *img = nil;
@try {
- if (self.remote_id == 127) {
- NSLog(@"%@", self.usericon);
- }
if (data != nil && [data isKindOfClass:[NSData class]]) {
img = [UIImage imageWithData:(NSData*)data];
}
From b12008a917a271d49104f90e94e150ee406b97c2 Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Sun, 27 Oct 2019 19:22:36 +0100
Subject: [PATCH 02/11] Disable logs
---
SUPLA/ChartDetailView.m | 4 ++--
SUPLA/Database.m | 1 -
SUPLA/MainVC.m | 4 ++--
3 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/SUPLA/ChartDetailView.m b/SUPLA/ChartDetailView.m
index d39d25c5..e405d327 100644
--- a/SUPLA/ChartDetailView.m
+++ b/SUPLA/ChartDetailView.m
@@ -103,12 +103,12 @@ -(void) runDownloadTask {
}
-(void) onRestApiTaskStarted: (SARestApiClientTask*)task {
- NSLog(@"onRestApiTaskStarted");
+ // NSLog(@"onRestApiTaskStarted");
[self.lPreloader animateWithTimeInterval:0.1];
}
-(void) onRestApiTaskFinished: (SARestApiClientTask*)task {
- NSLog(@"onRestApiTaskFinished");
+ // NSLog(@"onRestApiTaskFinished");
if (_task != nil && task == _task) {
_task.delegate = nil;
_task = nil;
diff --git a/SUPLA/Database.m b/SUPLA/Database.m
index 1685f403..7ca71d6a 100644
--- a/SUPLA/Database.m
+++ b/SUPLA/Database.m
@@ -1334,7 +1334,6 @@ -(void) deleteAllUserIcons {
del = YES;
for(int a=0;a
Date: Tue, 29 Oct 2019 19:01:46 +0100
Subject: [PATCH 03/11] XIB group
---
SUPLA.xcodeproj/project.pbxproj | 54 +++++++++++++++++++--------------
1 file changed, 31 insertions(+), 23 deletions(-)
diff --git a/SUPLA.xcodeproj/project.pbxproj b/SUPLA.xcodeproj/project.pbxproj
index f2f86c6d..57f8b9e3 100644
--- a/SUPLA.xcodeproj/project.pbxproj
+++ b/SUPLA.xcodeproj/project.pbxproj
@@ -995,6 +995,36 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
+ 012119122368B597004C1993 /* xib */ = {
+ isa = PBXGroup;
+ children = (
+ 01C8EBCF23422AC50072AB8C /* HomePlusDetailViewGroupCell.xib */,
+ 40CE7C6D1DCBBF6D00BBACE4 /* DistanceCell.xib */,
+ 017A3C8823633A70004AD1FC /* TempHumidityDetailView.xib */,
+ 01902A29235A1840005ED935 /* TemperatureDetailView.xib */,
+ 407D4AFE1BC6E491009A5505 /* StatusVC.xib */,
+ 40BE3E611BCA7AEF00153680 /* ChannelCell.xib */,
+ 406778541BCBF9F4008DD37F /* SectionCell.xib */,
+ 40DE1A3A1BCD5E9B004CF43B /* AboutVC.xib */,
+ 4038A5531CE32B6800180B5D /* TempHumidityCell.xib */,
+ 40DB208F1DC9049400FAFAB0 /* RGBDetail.xib */,
+ 019F4CAE2354DC3300286139 /* ImpulseCounterDetailView.xib */,
+ 01D0617322C296850043C947 /* ElectricityMeterDetailView.xib */,
+ 01C8EBFC234232EC0072AB8C /* HomePlusDetailView.xib */,
+ 40CE7C631DCBBCE400BBACE4 /* MeasurementCell.xib */,
+ 40F951471FD0654900698587 /* RSDetail.xib */,
+ 407D31961FD1A7070062FB80 /* AddWizardVC.xib */,
+ 4077ACE220A21BB100BD2216 /* CreateAccountVC.xib */,
+ 01F9111022EF989100BFF91D /* HomePlusCell.xib */,
+ 40844D811FB0DDB000432AA0 /* SettingsVC.xib */,
+ 401CA1EE1BA0923600117AF4 /* MainVC.xib */,
+ 408034E41BC84A89007666E7 /* NavigationController.xib */,
+ 01D4293922AAAA450050C1A2 /* IncrementalMeterCell.xib */,
+ 406778281BCBBC83008DD37F /* ThermometerCell.xib */,
+ );
+ name = xib;
+ sourceTree = "";
+ };
013D1C5A22CE4751000C0784 /* charts */ = {
isa = PBXGroup;
children = (
@@ -1497,7 +1527,7 @@
40A675851BA1BEBF004A51C4 /* UI */ = {
isa = PBXGroup;
children = (
- 40844D811FB0DDB000432AA0 /* SettingsVC.xib */,
+ 012119122368B597004C1993 /* xib */,
40C9E4FB1F2B841400753796 /* SAColorListPicker.h */,
40C9E4FC1F2B841400753796 /* SAColorListPicker.m */,
40C9E4F51F2A186A00753796 /* SARollerShutter.h */,
@@ -1507,33 +1537,23 @@
4031ACFA1BBC0FFB00CF9D8B /* MGSwipe */,
40A675801BA1BE8E004A51C4 /* SettingsVC.h */,
40A675811BA1BE8E004A51C4 /* SettingsVC.m */,
- 401CA1EE1BA0923600117AF4 /* MainVC.xib */,
401CA1C61BA067DB00117AF4 /* MainVC.h */,
401CA1C71BA067DB00117AF4 /* MainVC.m */,
4017E1291BB9CE2900570AC8 /* ChannelCell.h */,
4017E12A1BB9CE2900570AC8 /* ChannelCell.m */,
407D4AFC1BC6E491009A5505 /* StatusVC.h */,
407D4AFD1BC6E491009A5505 /* StatusVC.m */,
- 407D4AFE1BC6E491009A5505 /* StatusVC.xib */,
40CF96DC1BC820E60030EFFF /* UIHelper.h */,
40CF96DD1BC820E60030EFFF /* UIHelper.m */,
408034E21BC84A89007666E7 /* NavigationController.h */,
408034E31BC84A89007666E7 /* NavigationController.m */,
- 408034E41BC84A89007666E7 /* NavigationController.xib */,
- 40BE3E611BCA7AEF00153680 /* ChannelCell.xib */,
- 01D4293922AAAA450050C1A2 /* IncrementalMeterCell.xib */,
- 406778281BCBBC83008DD37F /* ThermometerCell.xib */,
406778521BCBF9F4008DD37F /* SectionCell.h */,
406778531BCBF9F4008DD37F /* SectionCell.m */,
- 406778541BCBF9F4008DD37F /* SectionCell.xib */,
40DE1A331BCD1B55004CF43B /* AboutVC.h */,
40DE1A341BCD1B55004CF43B /* AboutVC.m */,
- 40DE1A3A1BCD5E9B004CF43B /* AboutVC.xib */,
40B397CE1BCE7F3200BE7D5A /* Launch Screen.storyboard */,
- 4038A5531CE32B6800180B5D /* TempHumidityCell.xib */,
4006E9081DC62D0A00C4456D /* DetailView.h */,
4006E9091DC62D0A00C4456D /* DetailView.m */,
- 40DB208F1DC9049400FAFAB0 /* RGBDetail.xib */,
403150F91DC769430075D2D2 /* RGBDetailView.h */,
01D0616C22C294D90043C947 /* ElectricityMeterDetailView.h */,
012023C0234E54ED00E131B7 /* ImpulseCounterDetailView.h */,
@@ -1541,30 +1561,19 @@
01392B38235CA8B1003A2BAD /* ChartDetailView.h */,
01392B39235CA8B1003A2BAD /* ChartDetailView.m */,
01902A23235A17E9005ED935 /* TemperatureDetailView.h */,
- 017A3C8823633A70004AD1FC /* TempHumidityDetailView.xib */,
- 01902A29235A1840005ED935 /* TemperatureDetailView.xib */,
01902A24235A17E9005ED935 /* TemperatureDetailView.m */,
01902A26235A180F005ED935 /* TempHumidityDetailView.h */,
01902A27235A180F005ED935 /* TempHumidityDetailView.m */,
- 019F4CAE2354DC3300286139 /* ImpulseCounterDetailView.xib */,
01D0616D22C294D90043C947 /* ElectricityMeterDetailView.m */,
- 01D0617322C296850043C947 /* ElectricityMeterDetailView.xib */,
- 01C8EBFC234232EC0072AB8C /* HomePlusDetailView.xib */,
403150FA1DC769430075D2D2 /* RGBDetailView.m */,
- 40CE7C631DCBBCE400BBACE4 /* MeasurementCell.xib */,
- 40CE7C6D1DCBBF6D00BBACE4 /* DistanceCell.xib */,
409934B41F30EF9C003110C5 /* RSDetailView.h */,
409934B51F30EF9C003110C5 /* RSDetailView.m */,
- 40F951471FD0654900698587 /* RSDetail.xib */,
403EB1111FBDF47F00AD6460 /* AddWizardVC.h */,
403EB1121FBDF47F00AD6460 /* AddWizardVC.m */,
- 407D31961FD1A7070062FB80 /* AddWizardVC.xib */,
4077ACE020A21BB100BD2216 /* CreateAccountVC.h */,
4077ACE120A21BB100BD2216 /* CreateAccountVC.m */,
- 4077ACE220A21BB100BD2216 /* CreateAccountVC.xib */,
40B610CA20C7E263002B762A /* SAUIChannelStatus.h */,
40B610CB20C7E263002B762A /* SAUIChannelStatus.m */,
- 01F9111022EF989100BFF91D /* HomePlusCell.xib */,
017554F422F1A62500EB58B7 /* HomePlusDetailView.h */,
017554F522F1A62500EB58B7 /* HomePlusDetailView.m */,
0122613722F396440013E6A2 /* SAThermostatCalendar.h */,
@@ -1573,7 +1582,6 @@
0122613822F396440013E6A2 /* SAThermostatCalendar.m */,
019D22EE233CC2D000F17135 /* SAPreloader.h */,
019D22EF233CC2D000F17135 /* SAPreloader.m */,
- 01C8EBCF23422AC50072AB8C /* HomePlusDetailViewGroupCell.xib */,
);
name = UI;
sourceTree = "";
From ac474c6d3211e5f3ad7624e05caf6cdfda2dd762 Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Tue, 29 Oct 2019 20:11:57 +0100
Subject: [PATCH 04/11] Location collapse
---
SUPLA.xcodeproj/project.pbxproj | 8 +-
SUPLA/Database.h | 1 +
SUPLA/Database.m | 6 +-
SUPLA/MainVC.h | 5 +-
SUPLA/MainVC.m | 84 +++++++++-
SUPLA/NavigationController.m | 6 +-
SUPLA/Resources/Assets/Img/collapsed@3x.png | Bin 0 -> 1180 bytes
SUPLA/SUPLA.xcdatamodeld/.xccurrentversion | 2 +-
.../SUPLA 5.xcdatamodel/contents | 146 ++++++++++++++++++
SUPLA/SectionCell.h | 9 +-
SUPLA/SectionCell.m | 33 +++-
SUPLA/SectionCell.xib | 31 +++-
SUPLA/_SALocation+CoreDataProperties.h | 33 ++--
SUPLA/_SALocation+CoreDataProperties.m | 35 +++--
14 files changed, 336 insertions(+), 63 deletions(-)
create mode 100644 SUPLA/Resources/Assets/Img/collapsed@3x.png
create mode 100644 SUPLA/SUPLA.xcdatamodeld/SUPLA 5.xcdatamodel/contents
diff --git a/SUPLA.xcodeproj/project.pbxproj b/SUPLA.xcodeproj/project.pbxproj
index 57f8b9e3..0a8ee361 100644
--- a/SUPLA.xcodeproj/project.pbxproj
+++ b/SUPLA.xcodeproj/project.pbxproj
@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
012023C2234E54ED00E131B7 /* ImpulseCounterDetailView.m in Sources */ = {isa = PBXBuildFile; fileRef = 012023C1234E54ED00E131B7 /* ImpulseCounterDetailView.m */; };
+ 012119152368C3B2004C1993 /* collapsed@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = 012119142368C3B2004C1993 /* collapsed@3x.png */; };
0122613922F396440013E6A2 /* SAThermostatCalendar.m in Sources */ = {isa = PBXBuildFile; fileRef = 0122613822F396440013E6A2 /* SAThermostatCalendar.m */; };
012F722C22DF3E2300E5F72E /* ChartFilterFieldTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 012F722822DF3CF000E5F72E /* ChartFilterFieldTests.m */; };
012F722E22DFA0BE00E5F72E /* SABarChartDataSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 012F722D22DFA0BE00E5F72E /* SABarChartDataSet.swift */; };
@@ -363,6 +364,8 @@
/* Begin PBXFileReference section */
012023C0234E54ED00E131B7 /* ImpulseCounterDetailView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ImpulseCounterDetailView.h; sourceTree = ""; };
012023C1234E54ED00E131B7 /* ImpulseCounterDetailView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ImpulseCounterDetailView.m; sourceTree = ""; };
+ 012119132368BDB0004C1993 /* SUPLA 5.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "SUPLA 5.xcdatamodel"; sourceTree = ""; };
+ 012119142368C3B2004C1993 /* collapsed@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "collapsed@3x.png"; path = "Resources/Assets/Img/collapsed@3x.png"; sourceTree = ""; };
0122613722F396440013E6A2 /* SAThermostatCalendar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SAThermostatCalendar.h; sourceTree = ""; };
0122613822F396440013E6A2 /* SAThermostatCalendar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SAThermostatCalendar.m; sourceTree = ""; };
012F722822DF3CF000E5F72E /* ChartFilterFieldTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChartFilterFieldTests.m; sourceTree = ""; };
@@ -1214,6 +1217,7 @@
405AC4011BC15878004F7311 /* Img */ = {
isa = PBXGroup;
children = (
+ 012119142368C3B2004C1993 /* collapsed@3x.png */,
017A3CA523635C22004AD1FC /* weight@2x.png */,
017A3CA623635C22004AD1FC /* weight@3x.png */,
017A3CAD23635DF7004AD1FC /* pressure@2x.png */,
@@ -1715,6 +1719,7 @@
4052DA0D1DC515AE000B8C45 /* rgb-off@2x.png in Resources */,
40CE7C6B1DCBBD5700BBACE4 /* depth@2x.png in Resources */,
40DE1A2D1BCCFF8A004CF43B /* settings@2x.png in Resources */,
+ 012119152368C3B2004C1993 /* collapsed@3x.png in Resources */,
405AC4341BC15C08004F7311 /* logo-supla@2x.png in Resources */,
405C49A11FCAFFD400C15602 /* wizard_ok@2x.png in Resources */,
017A3C8623633A70004AD1FC /* TempHumidityDetailView.xib in Resources */,
@@ -2623,12 +2628,13 @@
407004251BB5706500F6187F /* SUPLA.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
+ 012119132368BDB0004C1993 /* SUPLA 5.xcdatamodel */,
01CFF6D12365BCCD00C827FB /* SUPLA 4.xcdatamodel */,
01B216CF22AECB2F004E0596 /* SUPLA 3.xcdatamodel */,
40BBA34620AC52EA0054CD20 /* SUPLA 2.xcdatamodel */,
407004261BB5706500F6187F /* SUPLA.xcdatamodel */,
);
- currentVersion = 01CFF6D12365BCCD00C827FB /* SUPLA 4.xcdatamodel */;
+ currentVersion = 012119132368BDB0004C1993 /* SUPLA 5.xcdatamodel */;
path = SUPLA.xcdatamodeld;
sourceTree = "";
versionGroupType = wrapper.xcdatamodel;
diff --git a/SUPLA/Database.h b/SUPLA/Database.h
index 10ffcb45..e925394a 100644
--- a/SUPLA/Database.h
+++ b/SUPLA/Database.h
@@ -61,6 +61,7 @@ typedef NS_ENUM(NSUInteger, GroupBy) {
- (void)saveContext;
-(_SALocation*) fetchLocationById:(int)location_id;
+-(NSArray*) fetchVisibleLocations;
-(_SALocation*) newLocation;
-(BOOL) updateLocation:(TSC_SuplaLocation *)location;
diff --git a/SUPLA/Database.m b/SUPLA/Database.m
index 7ca71d6a..b10fd9e4 100644
--- a/SUPLA/Database.m
+++ b/SUPLA/Database.m
@@ -62,7 +62,7 @@ - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
return _persistentStoreCoordinator;
}
- int DBv = 7;
+ int DBv = 8;
[self removeIfExists:@"SUPLA_DB.sqlite"];
@@ -250,6 +250,10 @@ -(_SALocation*) fetchLocationById:(int)location_id {
return [self fetchItemByPredicate:[NSPredicate predicateWithFormat:@"location_id = %i", location_id] entityName:@"SALocation"];
};
+-(NSArray*) fetchVisibleLocations {
+ return [self fetchByPredicate:[NSPredicate predicateWithFormat:@"visible > 0"] entityName:@"SALocation" limit:0 sortDescriptors:nil];
+}
+
-(_SALocation*) newLocation {
_SALocation *Location = [[_SALocation alloc] initWithEntity:[NSEntityDescription entityForName:@"SALocation" inManagedObjectContext:self.managedObjectContext] insertIntoManagedObjectContext:self.managedObjectContext];
diff --git a/SUPLA/MainVC.h b/SUPLA/MainVC.h
index 908e33a8..c998162a 100644
--- a/SUPLA/MainVC.h
+++ b/SUPLA/MainVC.h
@@ -18,10 +18,11 @@
#import
#import "SADownloadUserIcons.h"
+#import "SectionCell.h"
@class SADetailView;
-@interface SAMainVC : UIViewController
+@interface SAMainVC : UIViewController
- (IBAction)settingsTouched:(id)sender;
@@ -34,7 +35,7 @@
@property (weak, nonatomic) IBOutlet UILabel *notificationLabel;
- (void)detailHide;
-
+- (void)groupTableHidden:(BOOL)hidden;
@end
diff --git a/SUPLA/MainVC.m b/SUPLA/MainVC.m
index 23c53cd0..94764811 100644
--- a/SUPLA/MainVC.m
+++ b/SUPLA/MainVC.m
@@ -22,7 +22,6 @@
#import "SuplaApp.h"
#import "Database.h"
#import "SAChannel+CoreDataClass.h"
-#import "SectionCell.h"
#import "RGBDetailView.h"
#import "RSDetailView.h"
#import "ElectricityMeterDetailView.h"
@@ -31,6 +30,7 @@
#import "TemperatureDetailView.h"
#import "TempHumidityDetailView.h"
#import "SARateApp.h"
+#import "_SALocation+CoreDataClass.h"
@implementation SAMainVC {
NSFetchedResultsController *_cFrc;
@@ -46,7 +46,7 @@ @implementation SAMainVC {
NSTimer *_nTimer;
UITapGestureRecognizer *_tapRecognizer;
SADownloadUserIcons *_task;
-
+ NSArray *_locations;
}
- (void)registerNibForTableView:(UITableView*)tv {
@@ -104,6 +104,8 @@ - (void)didReceiveMemoryWarning {
-(void)onDataChanged {
_cFrc = nil;
_gFrc = nil;
+ _locations = nil;
+
[self.cTableView reloadData];
[self.gTableView reloadData];
}
@@ -231,6 +233,27 @@ - (void)detailHide {
[(SAMainView*)self.view detailShow:NO animated:NO];
}
+#pragma mark Locations
+
+- (_SALocation *) locationByName:(NSString *)name {
+ if (name == nil) {
+ return nil;
+ }
+
+ if (_locations == nil) {
+ _locations = [SAApp.DB fetchVisibleLocations];
+ if (_locations == nil) {
+ _locations = [[NSArray alloc] init];
+ }
+ }
+
+ NSUInteger idx = [_locations indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
+ return [((_SALocation*)obj).caption isEqualToString:name];
+ }];
+
+ return idx == NSNotFound ? nil : (_SALocation*)[_locations objectAtIndex:idx];
+}
+
#pragma mark Table Support
- (NSFetchedResultsController*)frcForTableView:(UITableView*)tableView {
@@ -261,16 +284,42 @@ - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInte
return [[[[self frcForTableView:tableView] sections] objectAtIndex:section] name];
}
+- (short)bitFlagCollapse {
+ return self.cTableView.hidden == NO ? 0x1 : 0x2;
+}
+
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+
NSFetchedResultsController *frc = [self frcForTableView:tableView];
if ( frc ) {
id sectionInfo = [[frc sections] objectAtIndex:section];
+ _SALocation *location = [self locationByName:sectionInfo.name];
+ if (location != nil
+ && (location.collapsed & [self bitFlagCollapse]) > 0) {
+ return 0;
+ }
return [sectionInfo numberOfObjects];
}
return 0;
}
+- (void)sectionCellTouch:(SASectionCell*)section {
+
+ _SALocation *location = [self locationByName:section.label.text];
+ if (location) {
+ short bit = [self bitFlagCollapse];
+ if ((location.collapsed & bit) > 0) {
+ location.collapsed ^= bit;
+ } else {
+ location.collapsed |= bit;
+ }
+
+ [SAApp.DB saveContext];
+ [self onDataChanged];
+ }
+}
+
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
SAChannelBase *channel_base = [[self frcForTableView:tableView] objectAtIndexPath:indexPath];
@@ -320,9 +369,12 @@ -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)
{
SASectionCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SectionCell"];
if ( cell ) {
- [cell.label setText:[[[[self frcForTableView:tableView] sections] objectAtIndex:section] name]];
+ NSString *name = [[[[self frcForTableView:tableView] sections] objectAtIndex:section] name];
+ _SALocation *location = [self locationByName:name];
+ cell.ivCollapsed.hidden = location == nil || (location.collapsed & [self bitFlagCollapse]) == 0;
+ [cell.label setText:name];
+ cell.delegate = self;
}
-
return cell;
}
@@ -331,6 +383,13 @@ - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSIntege
return 50;
}
+- (void)groupTableHidden:(BOOL)hidden {
+ self.cTableView.hidden = !hidden;
+ self.gTableView.hidden = hidden;
+
+ [self onDataChanged];
+}
+
- (IBAction)settingsTouched:(id)sender {
[[SAApp UI ] showSettings];
@@ -409,7 +468,6 @@ -(void)initMainView {
_animating = NO;
_panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[self addGestureRecognizer:_panRecognizer];
-
}
-(SADetailView*)detailView {
@@ -638,12 +696,9 @@ - (void)detailShow:(BOOL)show animated:(BOOL)animated {
}
}
-
-
}
-
- (void)handlePan:(UIPanGestureRecognizer *)gr {
if ( _animating )
@@ -724,5 +779,18 @@ -(void)moveCenter:(float)x_offset {
[self setCenter:CGPointMake(self.center.x+x_offset, self.center.y)];
}
+- (void)handleTap:(UITapGestureRecognizer *)gr {
+ if ( _animating )
+ return;
+
+ UITableView *tableView = self.cTableView.hidden ? self.gTableView : self.cTableView;
+ CGPoint touch_point = [gr locationInView:tableView];
+ NSIndexPath *path = [tableView indexPathForRowAtPoint:touch_point];
+
+ SASectionCell *section = [tableView cellForRowAtIndexPath:path];
+ if ([section isKindOfClass:[SASectionCell class]]) {
+
+ }
+}
@end
diff --git a/SUPLA/NavigationController.m b/SUPLA/NavigationController.m
index 8f35e534..80bad274 100644
--- a/SUPLA/NavigationController.m
+++ b/SUPLA/NavigationController.m
@@ -212,13 +212,11 @@ - (IBAction)groupsTouch:(id)sender {
if ( self.btnGroups.tag == 1 ) {
[self.btnGroups setImage:[UIImage imageNamed:@"groupsoff.png"]];
self.btnGroups.tag = 0;
- MainVC.cTableView.hidden = NO;
- MainVC.gTableView.hidden = YES;
+ [MainVC groupTableHidden: YES];
} else {
[self.btnGroups setImage:[UIImage imageNamed:@"groupson.png"]];
self.btnGroups.tag = 1;
- MainVC.cTableView.hidden = YES;
- MainVC.gTableView.hidden = NO;
+ [MainVC groupTableHidden: NO];
}
}
diff --git a/SUPLA/Resources/Assets/Img/collapsed@3x.png b/SUPLA/Resources/Assets/Img/collapsed@3x.png
new file mode 100644
index 0000000000000000000000000000000000000000..89d3f8e5b73e4e5488b0783afcb1965432cf6802
GIT binary patch
literal 1180
zcmeAS@N?(olHy`uVBq!ia0vp^zkqlS2OE$KbKF)1q}Y^7$z`G_|-Yj0w}^+
z;1O92)Nvhz8J#p{R{#asOFVsD*&nm;b8~3Vy#8`C0|Seur;B4q#jUq@Z?6>&6k)zF
zLra6L^VUR-HoXVjoQiVaC#IymdCGTgo49$+*|%j5`)Ypw`m1I%WAV26%JRQ{K3={e
zPHdum^>52p3pbqp75^zc&)(fmq%89P&VOs(K7Y}ENbmK3_4;Gqiraw9)hFg}{X6F=
zP^H$V^c?&2DvdXry8c|eeg38#*X}h+^-sPP9|J3s2P*ptR^|>=RtHvg52#EYq-_85
zZ^f-(W$(BCje(d}ons#kF>UYd^H(9Jo&Q#R6s+w2uD>x5)3yVZK}_2UR0cM!{_MBQ
z9|CTqivIN8K7Sfmef*}sCbmF7xc=M!cKKVdGwO5gd-+>q!zTXE{he70c8~vU|If~e
z(?g%^&$oXIk=ylGr}l$DS)}tnV|fwn3C-&gHa0e;e0^AV%z59IuWRHFd{KAxJ7akm1dQ@A*1i4M4G6SH%s^_x7*UU<0WW
zVLixK`M+(E21u`;2%Ghjzq30ZfvnOFQ~+sG>1qLKa#;w{)Tto`(j>roIFI?SbjPB^
z>$UaY11;WIy?<}h)gF8OZ|re~gzJU%#|>GWFXYy5H{@u(kXgUnkmvA))cWa$0?Zc^
z>)Q=QoG-@Kmm5knUyQ6zHmQv>v?hB+>-F5_ONw~`c((*d&^@;Qa(i^08mFG9*oygnVRl~Q-ara53Po6K@
z-imeK-#h#7s^yKl8DDI;&M#YZAyNEFVdQ&MBb@0Hc#J9smFU
literal 0
HcmV?d00001
diff --git a/SUPLA/SUPLA.xcdatamodeld/.xccurrentversion b/SUPLA/SUPLA.xcdatamodeld/.xccurrentversion
index 2c8560c4..5f761ffa 100644
--- a/SUPLA/SUPLA.xcdatamodeld/.xccurrentversion
+++ b/SUPLA/SUPLA.xcdatamodeld/.xccurrentversion
@@ -3,6 +3,6 @@
_XCCurrentVersionName
- SUPLA 4.xcdatamodel
+ SUPLA 5.xcdatamodel
diff --git a/SUPLA/SUPLA.xcdatamodeld/SUPLA 5.xcdatamodel/contents b/SUPLA/SUPLA.xcdatamodeld/SUPLA 5.xcdatamodel/contents
new file mode 100644
index 00000000..0b9e6673
--- /dev/null
+++ b/SUPLA/SUPLA.xcdatamodeld/SUPLA 5.xcdatamodel/contents
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SUPLA/SectionCell.h b/SUPLA/SectionCell.h
index 28fa1402..e2acb9ad 100644
--- a/SUPLA/SectionCell.h
+++ b/SUPLA/SectionCell.h
@@ -18,7 +18,14 @@
#import
+@class SASectionCell;
+@protocol SASectionCellDelegate
+@optional
+- (void)sectionCellTouch:(SASectionCell*)section;
+@end
+
@interface SASectionCell : UITableViewCell
+@property (weak, nonatomic) IBOutlet UIImageView *ivCollapsed;
@property (weak, nonatomic) IBOutlet UILabel *label;
-
+@property (nonatomic, weak, nullable) id delegate;
@end
diff --git a/SUPLA/SectionCell.m b/SUPLA/SectionCell.m
index 914a6d2b..4adc43ef 100644
--- a/SUPLA/SectionCell.m
+++ b/SUPLA/SectionCell.m
@@ -18,13 +18,38 @@
#import "SectionCell.h"
-@implementation SASectionCell
+@implementation SASectionCell {
+ UITapGestureRecognizer *_tap;
+}
+- (void)initialize {
+ if (_tap == nil) {
+ _tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapped:)];
+ _tap.delegate = self;
+ [self addGestureRecognizer:_tap];
+ }
+}
-- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
- [super setSelected:selected animated:animated];
+- (id)initWithCoder:(NSCoder *)coder
+{
+ self = [super initWithCoder:coder];
+ if (self) {
+ [self initialize];
+ }
+ return self;
+}
- // Configure the view for the selected state
+- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(nullable NSString *)reuseIdentifier {
+ self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
+ if (self) {
+ [self initialize];
+ }
+ return self;
}
+- (void)tapped:(UITapGestureRecognizer *)gr {
+ if (self.delegate) {
+ [self.delegate sectionCellTouch:self];
+ }
+}
@end
diff --git a/SUPLA/SectionCell.xib b/SUPLA/SectionCell.xib
index eedbbf7a..0961f9a2 100644
--- a/SUPLA/SectionCell.xib
+++ b/SUPLA/SectionCell.xib
@@ -1,13 +1,13 @@
-
-
+
+
+
-
-
+
-
+
Quicksand-Regular
@@ -18,35 +18,50 @@
-
+
+
+
+
+
+
+
+
+
-
+
+
+
+
-
+
+
+
+
diff --git a/SUPLA/_SALocation+CoreDataProperties.h b/SUPLA/_SALocation+CoreDataProperties.h
index 067b9965..d0274d7a 100644
--- a/SUPLA/_SALocation+CoreDataProperties.h
+++ b/SUPLA/_SALocation+CoreDataProperties.h
@@ -1,20 +1,20 @@
/*
- Copyright (C) AC SOFTWARE SP. Z O.O.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
+Copyright (C) AC SOFTWARE SP. Z O.O.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
#import "_SALocation+CoreDataClass.h"
@@ -28,6 +28,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nullable, nonatomic, copy) NSString *caption;
@property (nullable, nonatomic, copy) NSNumber *location_id;
@property (nullable, nonatomic, copy) NSNumber *visible;
+@property (nonatomic) int16_t collapsed;
@end
diff --git a/SUPLA/_SALocation+CoreDataProperties.m b/SUPLA/_SALocation+CoreDataProperties.m
index 090c28aa..2293ca0f 100644
--- a/SUPLA/_SALocation+CoreDataProperties.m
+++ b/SUPLA/_SALocation+CoreDataProperties.m
@@ -1,31 +1,32 @@
/*
- Copyright (C) AC SOFTWARE SP. Z O.O.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- 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 General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
+Copyright (C) AC SOFTWARE SP. Z O.O.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
#import "_SALocation+CoreDataProperties.h"
@implementation _SALocation (CoreDataProperties)
+ (NSFetchRequest<_SALocation *> *)fetchRequest {
- return [[NSFetchRequest alloc] initWithEntityName:@"SALocation"];
+ return [NSFetchRequest fetchRequestWithEntityName:@"SALocation"];
}
@dynamic caption;
@dynamic location_id;
@dynamic visible;
+@dynamic collapsed;
@end
From 4e44556a431d2a06707c8edb8cc51a7f366c201c Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Fri, 1 Nov 2019 18:44:15 +0100
Subject: [PATCH 05/11] getRandom refactor
---
SuplaApp.m | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/SuplaApp.m b/SuplaApp.m
index 7bfdd551..31c33893 100644
--- a/SuplaApp.m
+++ b/SuplaApp.m
@@ -80,25 +80,25 @@ +(SAApp*)instance {
return _Globals;
}
-+(void) getRandomKey:(char*)key keySize:(int)size forPrefKey:(NSString*)pref_key {
++(void) getRandom:(char*)key size:(int)size forPrefKey:(NSString*)pref_key {
@synchronized(self) {
-
- NSData *KEY = [[NSUserDefaults standardUserDefaults] dataForKey:pref_key];
- if ( KEY == nil || [KEY length] != size ) {
+ NSData *randomData = [[NSUserDefaults standardUserDefaults] dataForKey:pref_key];
+
+ if ( randomData == nil || [randomData length] != size ) {
- NSMutableData* newKEY = [NSMutableData dataWithCapacity:size];
+ NSMutableData* newRandomData = [NSMutableData dataWithCapacity:size];
for( int i = 0 ; i < size; ++i ) {
Byte random = arc4random();
- [newKEY appendBytes:(void*)&random length:1];
+ [newRandomData appendBytes:(void*)&random length:1];
}
- [[NSUserDefaults standardUserDefaults] setValue:newKEY forKey:pref_key];
- KEY = newKEY;
+ [[NSUserDefaults standardUserDefaults] setValue:newRandomData forKey:pref_key];
+ randomData = newRandomData;
};
- if ( KEY && [KEY length] == size ) {
- [KEY getBytes:key length:size];
+ if ( randomData && [randomData length] == size ) {
+ [randomData getBytes:key length:size];
} else {
memset(key, 0, size);
}
@@ -109,11 +109,11 @@ +(void) getRandomKey:(char*)key keySize:(int)size forPrefKey:(NSString*)pref_key
+(void) getClientGUID:(char[SUPLA_GUID_SIZE])guid {
// TODO: Implement guid encryption with password based on device id
- [SAApp getRandomKey:guid keySize:SUPLA_GUID_SIZE forPrefKey:@"client_guid"];
+ [SAApp getRandom:guid size:SUPLA_GUID_SIZE forPrefKey:@"client_guid"];
}
+(void) getAuthKey:(char [SUPLA_AUTHKEY_SIZE])auth_key {
- [SAApp getRandomKey:auth_key keySize:SUPLA_AUTHKEY_SIZE forPrefKey:@"auth_key"];
+ [SAApp getRandom:auth_key size:SUPLA_AUTHKEY_SIZE forPrefKey:@"auth_key"];
}
-(int) getCfgVersion {
From 2ee342b8399f2b55b3d5beb6412ac212be25c100 Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Fri, 1 Nov 2019 20:06:21 +0100
Subject: [PATCH 06/11] NSData AES category + Test
---
SUPLA.xcodeproj/project.pbxproj | 10 +++++
SUPLA/NSData+AES.h | 28 +++++++++++++
SUPLA/NSData+AES.m | 65 +++++++++++++++++++++++++++++++
SUPLATests/NSDataEncryptionTest.m | 57 +++++++++++++++++++++++++++
4 files changed, 160 insertions(+)
create mode 100644 SUPLA/NSData+AES.h
create mode 100644 SUPLA/NSData+AES.m
create mode 100644 SUPLATests/NSDataEncryptionTest.m
diff --git a/SUPLA.xcodeproj/project.pbxproj b/SUPLA.xcodeproj/project.pbxproj
index 0a8ee361..173fca33 100644
--- a/SUPLA.xcodeproj/project.pbxproj
+++ b/SUPLA.xcodeproj/project.pbxproj
@@ -89,6 +89,8 @@
01EE9BB022BA4B050029A142 /* SAChannelExtendedValue+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EE9BAF22BA4B050029A142 /* SAChannelExtendedValue+CoreDataProperties.m */; };
01EE9BBB22BA50D90029A142 /* SAChannelValueBase+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EE9BB722BA50D90029A142 /* SAChannelValueBase+CoreDataClass.m */; };
01EE9BBC22BA50D90029A142 /* SAChannelValueBase+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EE9BB822BA50D90029A142 /* SAChannelValueBase+CoreDataProperties.m */; };
+ 01EFD94A236CA94400893489 /* NSData+AES.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EFD949236CA94400893489 /* NSData+AES.m */; };
+ 01EFD94C236CA9AE00893489 /* NSDataEncryptionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EFD94B236CA9AE00893489 /* NSDataEncryptionTest.m */; };
01F8856922E5E79100D18373 /* SATempHumidityMeasurementItem+CoreDataClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 01F8855C22E5E79000D18373 /* SATempHumidityMeasurementItem+CoreDataClass.m */; };
01F8856A22E5E79100D18373 /* SATempHumidityMeasurementItem+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 01F8856322E5E79100D18373 /* SATempHumidityMeasurementItem+CoreDataProperties.m */; };
01F8856B22E5E79100D18373 /* SAThermostatMeasurementItem+CoreDataProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 01F8855522E5E79000D18373 /* SAThermostatMeasurementItem+CoreDataProperties.m */; };
@@ -591,6 +593,9 @@
01EE9BB622BA50D90029A142 /* SAChannelValueBase+CoreDataClass.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SAChannelValueBase+CoreDataClass.h"; sourceTree = ""; };
01EE9BB722BA50D90029A142 /* SAChannelValueBase+CoreDataClass.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SAChannelValueBase+CoreDataClass.m"; sourceTree = ""; };
01EE9BB822BA50D90029A142 /* SAChannelValueBase+CoreDataProperties.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SAChannelValueBase+CoreDataProperties.m"; sourceTree = ""; };
+ 01EFD948236CA94400893489 /* NSData+AES.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSData+AES.h"; sourceTree = ""; };
+ 01EFD949236CA94400893489 /* NSData+AES.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSData+AES.m"; sourceTree = ""; };
+ 01EFD94B236CA9AE00893489 /* NSDataEncryptionTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSDataEncryptionTest.m; sourceTree = ""; };
01F8855522E5E79000D18373 /* SAThermostatMeasurementItem+CoreDataProperties.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SAThermostatMeasurementItem+CoreDataProperties.m"; sourceTree = ""; };
01F8855622E5E79000D18373 /* SAImpulseCounterMeasurementItem+CoreDataClass.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SAImpulseCounterMeasurementItem+CoreDataClass.m"; sourceTree = ""; };
01F8855722E5E79000D18373 /* SAImpulseCounterMeasurementItem+CoreDataProperties.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SAImpulseCounterMeasurementItem+CoreDataProperties.h"; sourceTree = ""; };
@@ -1140,6 +1145,8 @@
40A675851BA1BEBF004A51C4 /* UI */,
40A6757D1BA1A5B6004A51C4 /* SuplaApp.h */,
40A6757E1BA1A5B6004A51C4 /* SuplaApp.m */,
+ 01EFD948236CA94400893489 /* NSData+AES.h */,
+ 01EFD949236CA94400893489 /* NSData+AES.m */,
401CA1C01BA067DB00117AF4 /* AppDelegate.h */,
401CA1C11BA067DB00117AF4 /* AppDelegate.m */,
401CA1CC1BA067DB00117AF4 /* Images.xcassets */,
@@ -1168,6 +1175,7 @@
401CA1D81BA067DB00117AF4 /* SUPLATests */ = {
isa = PBXGroup;
children = (
+ 01EFD94B236CA9AE00893489 /* NSDataEncryptionTest.m */,
012F722822DF3CF000E5F72E /* ChartFilterFieldTests.m */,
401CA1DB1BA067DB00117AF4 /* SUPLATests.m */,
401CA1D91BA067DB00117AF4 /* Supporting Files */,
@@ -2038,6 +2046,7 @@
019D22F0233CC2D000F17135 /* SAPreloader.m in Sources */,
40DE1A361BCD1B55004CF43B /* AboutVC.m in Sources */,
4017E12C1BB9CE2900570AC8 /* ChannelCell.m in Sources */,
+ 01EFD94A236CA94400893489 /* NSData+AES.m in Sources */,
01C1719222C7F3A2005983E1 /* SAElectricityMeasurementItem+CoreDataProperties.m in Sources */,
40AB8BDE1DCB32EB0030F3DE /* SARateApp.m in Sources */,
01C1719122C7F3A2005983E1 /* SAElectricityMeasurementItem+CoreDataClass.m in Sources */,
@@ -2133,6 +2142,7 @@
buildActionMask = 2147483647;
files = (
401CA1DC1BA067DB00117AF4 /* SUPLATests.m in Sources */,
+ 01EFD94C236CA9AE00893489 /* NSDataEncryptionTest.m in Sources */,
012F722C22DF3E2300E5F72E /* ChartFilterFieldTests.m in Sources */,
0130894523395F4C00F46FCD /* ThermostatScheduleCfgTests.m in Sources */,
012FCBD323217DE000AC6FF6 /* ThermostatCalendarTests.m in Sources */,
diff --git a/SUPLA/NSData+AES.h b/SUPLA/NSData+AES.h
new file mode 100644
index 00000000..644e0bfd
--- /dev/null
+++ b/SUPLA/NSData+AES.h
@@ -0,0 +1,28 @@
+/*
+Copyright (C) AC SOFTWARE SP. Z O.O.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface NSData (AES)
+- (NSData *)aes128EncryptWithKey:(NSString *)key;
+- (NSData *)aes128DecryptWithKey:(NSString *)key;
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/SUPLA/NSData+AES.m b/SUPLA/NSData+AES.m
new file mode 100644
index 00000000..66b0ed04
--- /dev/null
+++ b/SUPLA/NSData+AES.m
@@ -0,0 +1,65 @@
+/*
+Copyright (C) AC SOFTWARE SP. Z O.O.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import "NSData+AES.h"
+#import
+
+@implementation NSData (AES)
+
+-(NSData *)aes128Operation:(CCOperation)operation withKey:(NSString *)key {
+
+ while(key.length < 32) {
+ key = [NSString stringWithFormat:@"%@0", key];
+ }
+
+ key = [key substringToIndex:32];
+
+ size_t bufferSize = [self length] + kCCBlockSizeAES128 * 2;
+ void *buffer = malloc(bufferSize);
+
+ NSData *_key = [key dataUsingEncoding:NSUTF8StringEncoding];
+
+ size_t encryptedSize = 0;
+ CCCryptorStatus cryptStatus = CCCrypt(operation,
+ kCCAlgorithmAES128,
+ kCCOptionPKCS7Padding,
+ [_key bytes],
+ [_key length],
+ nil,
+ [self bytes],
+ [self length],
+ buffer,
+ bufferSize,
+ &encryptedSize);
+
+ if (cryptStatus == kCCSuccess && encryptedSize > 0) {
+ return [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
+ }
+
+ free(buffer);
+ return nil;
+}
+
+- (NSData *)aes128EncryptWithKey:(NSString *)key {
+ return [self aes128Operation:kCCEncrypt withKey:key];
+}
+
+- (NSData *)aes128DecryptWithKey:(NSString *)key {
+ return [self aes128Operation:kCCDecrypt withKey:key];
+}
+@end
diff --git a/SUPLATests/NSDataEncryptionTest.m b/SUPLATests/NSDataEncryptionTest.m
new file mode 100644
index 00000000..54c5fa91
--- /dev/null
+++ b/SUPLATests/NSDataEncryptionTest.m
@@ -0,0 +1,57 @@
+/*
+Copyright (C) AC SOFTWARE SP. Z O.O.
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#import
+#import "NSData+AES.h"
+
+@interface NSDataEncryptionTest : XCTestCase
+
+@end
+
+@implementation NSDataEncryptionTest
+
+- (void)testEncryption {
+
+ NSString *sourceText = @"ABCD";
+ NSData *sourceData = [sourceText dataUsingEncoding:NSUTF8StringEncoding];
+
+ // Key is aligned to 32 characters
+ NSData *encrypted = [sourceData aes128EncryptWithKey:@"X"];
+ XCTAssertNotNil(encrypted);
+ XCTAssertFalse([encrypted isEqualToData:sourceData]);
+
+ NSData *decrypted = [encrypted aes128DecryptWithKey:@"X"];
+ XCTAssertNotNil(decrypted);
+ XCTAssertFalse([encrypted isEqualToData:decrypted]);
+ XCTAssertTrue([decrypted isEqualToData:sourceData]);
+
+ NSString *decryptedText = [[NSString alloc]
+ initWithData:decrypted encoding:NSUTF8StringEncoding];
+ XCTAssertTrue([decryptedText isEqualToString:sourceText]);
+
+ decrypted = [encrypted aes128DecryptWithKey:@"Y"];
+ XCTAssertFalse([sourceData isEqualToData:decrypted]);
+
+ decrypted = [encrypted aes128DecryptWithKey:@"X000000000000000000000000000000Y"];
+ XCTAssertFalse([sourceData isEqualToData:decrypted]);
+
+ decrypted = [encrypted aes128DecryptWithKey:@"X0000000000000000000000000000000Y"];
+ XCTAssertTrue([sourceData isEqualToData:decrypted]);
+}
+
+@end
From 103c55fc74ca0410b933e0c1abfbfadfe9f875ab Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Fri, 1 Nov 2019 20:33:10 +0100
Subject: [PATCH 07/11] Encrypt GUID and AuthKey with device unique id
---
SUPLA/NSData+AES.h | 3 +++
SUPLA/NSData+AES.m | 12 ++++++++++++
SuplaApp.m | 36 ++++++++++++++++++++++++------------
3 files changed, 39 insertions(+), 12 deletions(-)
diff --git a/SUPLA/NSData+AES.h b/SUPLA/NSData+AES.h
index 644e0bfd..14da265c 100644
--- a/SUPLA/NSData+AES.h
+++ b/SUPLA/NSData+AES.h
@@ -23,6 +23,9 @@ NS_ASSUME_NONNULL_BEGIN
@interface NSData (AES)
- (NSData *)aes128EncryptWithKey:(NSString *)key;
- (NSData *)aes128DecryptWithKey:(NSString *)key;
+
+- (NSData *)aes128EncryptWithDeviceUniqueId;
+- (NSData *)aes128DecryptWithDeviceUniqueId;
@end
NS_ASSUME_NONNULL_END
diff --git a/SUPLA/NSData+AES.m b/SUPLA/NSData+AES.m
index 66b0ed04..85b45628 100644
--- a/SUPLA/NSData+AES.m
+++ b/SUPLA/NSData+AES.m
@@ -17,6 +17,7 @@
*/
#import "NSData+AES.h"
+#import
#import
@implementation NSData (AES)
@@ -62,4 +63,15 @@ - (NSData *)aes128EncryptWithKey:(NSString *)key {
- (NSData *)aes128DecryptWithKey:(NSString *)key {
return [self aes128Operation:kCCDecrypt withKey:key];
}
+
+- (NSData *)aes128EncryptWithDeviceUniqueId {
+ NSString *key = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
+ return [self aes128EncryptWithKey:key];
+}
+
+- (NSData *)aes128DecryptWithDeviceUniqueId {
+ NSString *key = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
+ return [self aes128DecryptWithKey:key];
+
+}
@end
diff --git a/SuplaApp.m b/SuplaApp.m
index 31c33893..0c445522 100644
--- a/SuplaApp.m
+++ b/SuplaApp.m
@@ -19,7 +19,7 @@
#import "SuplaApp.h"
#import "Database.h"
-
+#import "NSData+AES.h"
static SAApp* _Globals = nil;
@@ -80,25 +80,38 @@ +(SAApp*)instance {
return _Globals;
}
-+(void) getRandom:(char*)key size:(int)size forPrefKey:(NSString*)pref_key {
+-(void) encryptData:(NSData *)data andSaveWithPrefKey:(NSString *)pref_key {
+ @synchronized(self) {
+ data = [data aes128EncryptWithDeviceUniqueId];
+ [[NSUserDefaults standardUserDefaults] setValue:data forKey:pref_key];
+ [[NSUserDefaults standardUserDefaults] setBool:true forKey:[NSString stringWithFormat:@"%@_encrypted", pref_key]];
+ }
+}
+
+-(void) getRandom:(char*)key size:(int)size forPrefKey:(NSString*)pref_key {
@synchronized(self) {
- NSData *randomData = [[NSUserDefaults standardUserDefaults] dataForKey:pref_key];
+ NSData *data = [[NSUserDefaults standardUserDefaults] dataForKey:pref_key];
- if ( randomData == nil || [randomData length] != size ) {
-
+ if ([[NSUserDefaults standardUserDefaults] boolForKey:[NSString stringWithFormat:@"%@_encrypted", pref_key]]) {
+ data = [data aes128DecryptWithDeviceUniqueId];
+ } else {
+ [self encryptData:data andSaveWithPrefKey:pref_key];
+ }
+
+ if ( data == nil || [data length] != size ) {
NSMutableData* newRandomData = [NSMutableData dataWithCapacity:size];
for( int i = 0 ; i < size; ++i ) {
Byte random = arc4random();
[newRandomData appendBytes:(void*)&random length:1];
}
- [[NSUserDefaults standardUserDefaults] setValue:newRandomData forKey:pref_key];
- randomData = newRandomData;
+ [self encryptData:newRandomData andSaveWithPrefKey:pref_key];
+ data = newRandomData;
};
- if ( randomData && [randomData length] == size ) {
- [randomData getBytes:key length:size];
+ if ( data && [data length] == size ) {
+ [data getBytes:key length:size];
} else {
memset(key, 0, size);
}
@@ -108,12 +121,11 @@ +(void) getRandom:(char*)key size:(int)size forPrefKey:(NSString*)pref_key {
}
+(void) getClientGUID:(char[SUPLA_GUID_SIZE])guid {
- // TODO: Implement guid encryption with password based on device id
- [SAApp getRandom:guid size:SUPLA_GUID_SIZE forPrefKey:@"client_guid"];
+ [[self instance] getRandom:guid size:SUPLA_GUID_SIZE forPrefKey:@"client_guid"];
}
+(void) getAuthKey:(char [SUPLA_AUTHKEY_SIZE])auth_key {
- [SAApp getRandom:auth_key size:SUPLA_AUTHKEY_SIZE forPrefKey:@"auth_key"];
+ [[self instance] getRandom:auth_key size:SUPLA_AUTHKEY_SIZE forPrefKey:@"auth_key"];
}
-(int) getCfgVersion {
From 2a66d0ade0105debe41a9f346eb1e18d8b3b9186 Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Fri, 1 Nov 2019 20:33:29 +0100
Subject: [PATCH 08/11] Version increment
---
SUPLA.xcodeproj/project.pbxproj | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/SUPLA.xcodeproj/project.pbxproj b/SUPLA.xcodeproj/project.pbxproj
index 173fca33..4a8cf6c6 100644
--- a/SUPLA.xcodeproj/project.pbxproj
+++ b/SUPLA.xcodeproj/project.pbxproj
@@ -2527,7 +2527,7 @@
"$(inherited)",
"$(PROJECT_DIR)/SUPLA/lib",
);
- MARKETING_VERSION = 2.3.0;
+ MARKETING_VERSION = 2.3.1;
PRODUCT_BUNDLE_IDENTIFIER = com.acsoftware.ios.supla;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "SUPLA/SUPLA-Bridging-Header.h";
@@ -2554,7 +2554,7 @@
"$(inherited)",
"$(PROJECT_DIR)/SUPLA/lib",
);
- MARKETING_VERSION = 2.3.0;
+ MARKETING_VERSION = 2.3.1;
PRODUCT_BUNDLE_IDENTIFIER = com.acsoftware.ios.supla;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "SUPLA/SUPLA-Bridging-Header.h";
From 9fc03fe734576c119f36f786aa56759134ac59ae Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Fri, 1 Nov 2019 20:41:58 +0100
Subject: [PATCH 09/11] kCCBlockSizeAES128 * 1 is sufficient
---
SUPLA/NSData+AES.m | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/SUPLA/NSData+AES.m b/SUPLA/NSData+AES.m
index 85b45628..c7e3ae99 100644
--- a/SUPLA/NSData+AES.m
+++ b/SUPLA/NSData+AES.m
@@ -30,7 +30,7 @@ -(NSData *)aes128Operation:(CCOperation)operation withKey:(NSString *)key {
key = [key substringToIndex:32];
- size_t bufferSize = [self length] + kCCBlockSizeAES128 * 2;
+ size_t bufferSize = [self length] + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
NSData *_key = [key dataUsingEncoding:NSUTF8StringEncoding];
From ab116c29631df14e6a9d494f004b79d16ac8fe3f Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Fri, 1 Nov 2019 20:49:05 +0100
Subject: [PATCH 10/11] "key" renamed to "password"
---
SUPLA/NSData+AES.h | 4 ++--
SUPLA/NSData+AES.m | 28 +++++++++++++++-------------
SUPLATests/NSDataEncryptionTest.m | 10 +++++-----
3 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/SUPLA/NSData+AES.h b/SUPLA/NSData+AES.h
index 14da265c..14c59ef5 100644
--- a/SUPLA/NSData+AES.h
+++ b/SUPLA/NSData+AES.h
@@ -21,8 +21,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
NS_ASSUME_NONNULL_BEGIN
@interface NSData (AES)
-- (NSData *)aes128EncryptWithKey:(NSString *)key;
-- (NSData *)aes128DecryptWithKey:(NSString *)key;
+- (NSData *)aes128EncryptWithPassword:(NSString *)password;
+- (NSData *)aes128DecryptWithPassword:(NSString *)password;
- (NSData *)aes128EncryptWithDeviceUniqueId;
- (NSData *)aes128DecryptWithDeviceUniqueId;
diff --git a/SUPLA/NSData+AES.m b/SUPLA/NSData+AES.m
index c7e3ae99..21ec1361 100644
--- a/SUPLA/NSData+AES.m
+++ b/SUPLA/NSData+AES.m
@@ -22,18 +22,20 @@
@implementation NSData (AES)
--(NSData *)aes128Operation:(CCOperation)operation withKey:(NSString *)key {
+-(NSData *)aes128Operation:(CCOperation)operation withPassword:(NSString *)password {
- while(key.length < 32) {
- key = [NSString stringWithFormat:@"%@0", key];
+ // *Password
+ // This is not a good implementation but sufficient for current use
+ while(password.length < 32) {
+ password = [NSString stringWithFormat:@"%@0", password];
}
- key = [key substringToIndex:32];
+ password = [password substringToIndex:32];
size_t bufferSize = [self length] + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
- NSData *_key = [key dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *_key = [password dataUsingEncoding:NSUTF8StringEncoding];
size_t encryptedSize = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
@@ -56,22 +58,22 @@ -(NSData *)aes128Operation:(CCOperation)operation withKey:(NSString *)key {
return nil;
}
-- (NSData *)aes128EncryptWithKey:(NSString *)key {
- return [self aes128Operation:kCCEncrypt withKey:key];
+- (NSData *)aes128EncryptWithPassword:(NSString *)password {
+ return [self aes128Operation:kCCEncrypt withPassword:password];
}
-- (NSData *)aes128DecryptWithKey:(NSString *)key {
- return [self aes128Operation:kCCDecrypt withKey:key];
+- (NSData *)aes128DecryptWithPassword:(NSString *)password {
+ return [self aes128Operation:kCCDecrypt withPassword:password];
}
- (NSData *)aes128EncryptWithDeviceUniqueId {
- NSString *key = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
- return [self aes128EncryptWithKey:key];
+ NSString *pwd = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
+ return [self aes128EncryptWithPassword:pwd];
}
- (NSData *)aes128DecryptWithDeviceUniqueId {
- NSString *key = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
- return [self aes128DecryptWithKey:key];
+ NSString *pwd = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
+ return [self aes128DecryptWithPassword:pwd];
}
@end
diff --git a/SUPLATests/NSDataEncryptionTest.m b/SUPLATests/NSDataEncryptionTest.m
index 54c5fa91..13ef7a4b 100644
--- a/SUPLATests/NSDataEncryptionTest.m
+++ b/SUPLATests/NSDataEncryptionTest.m
@@ -31,11 +31,11 @@ - (void)testEncryption {
NSData *sourceData = [sourceText dataUsingEncoding:NSUTF8StringEncoding];
// Key is aligned to 32 characters
- NSData *encrypted = [sourceData aes128EncryptWithKey:@"X"];
+ NSData *encrypted = [sourceData aes128EncryptWithPassword:@"X"];
XCTAssertNotNil(encrypted);
XCTAssertFalse([encrypted isEqualToData:sourceData]);
- NSData *decrypted = [encrypted aes128DecryptWithKey:@"X"];
+ NSData *decrypted = [encrypted aes128DecryptWithPassword:@"X"];
XCTAssertNotNil(decrypted);
XCTAssertFalse([encrypted isEqualToData:decrypted]);
XCTAssertTrue([decrypted isEqualToData:sourceData]);
@@ -44,13 +44,13 @@ - (void)testEncryption {
initWithData:decrypted encoding:NSUTF8StringEncoding];
XCTAssertTrue([decryptedText isEqualToString:sourceText]);
- decrypted = [encrypted aes128DecryptWithKey:@"Y"];
+ decrypted = [encrypted aes128DecryptWithPassword:@"Y"];
XCTAssertFalse([sourceData isEqualToData:decrypted]);
- decrypted = [encrypted aes128DecryptWithKey:@"X000000000000000000000000000000Y"];
+ decrypted = [encrypted aes128DecryptWithPassword:@"X000000000000000000000000000000Y"];
XCTAssertFalse([sourceData isEqualToData:decrypted]);
- decrypted = [encrypted aes128DecryptWithKey:@"X0000000000000000000000000000000Y"];
+ decrypted = [encrypted aes128DecryptWithPassword:@"X0000000000000000000000000000000Y"];
XCTAssertTrue([sourceData isEqualToData:decrypted]);
}
From a906af9fba5bff454bdaf74868c803987f6fa0d7 Mon Sep 17 00:00:00 2001
From: Przemek Zygmunt
Date: Fri, 1 Nov 2019 21:14:59 +0100
Subject: [PATCH 11/11] Set %@_encrypted to false when encryption failed
---
SuplaApp.m | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/SuplaApp.m b/SuplaApp.m
index 0c445522..1a9c1811 100644
--- a/SuplaApp.m
+++ b/SuplaApp.m
@@ -82,9 +82,10 @@ +(SAApp*)instance {
-(void) encryptData:(NSData *)data andSaveWithPrefKey:(NSString *)pref_key {
@synchronized(self) {
- data = [data aes128EncryptWithDeviceUniqueId];
- [[NSUserDefaults standardUserDefaults] setValue:data forKey:pref_key];
- [[NSUserDefaults standardUserDefaults] setBool:true forKey:[NSString stringWithFormat:@"%@_encrypted", pref_key]];
+ NSData *encryptedData = [data aes128EncryptWithDeviceUniqueId];
+ NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
+ [ud setValue:(encryptedData != nil ? encryptedData : data) forKey:pref_key];
+ [ud setBool:(encryptedData != nil) forKey:[NSString stringWithFormat:@"%@_encrypted", pref_key]];
}
}