diff --git a/Classes/ImagePickerView.m b/Classes/ImagePickerView.m index 41b49d666..932c21b7f 100644 --- a/Classes/ImagePickerView.m +++ b/Classes/ImagePickerView.m @@ -22,10 +22,10 @@ #import "PhoneMainView.h" #import "SVProgressHUD.h" #import "ShareViewController.h" +#import "linphoneapp-Swift.h" #import - @implementation ImagePickerView @synthesize imagePickerDelegate; diff --git a/Classes/LinphoneCoreSettingsStore.h b/Classes/LinphoneCoreSettingsStore.h index 49180e690..b3e656704 100644 --- a/Classes/LinphoneCoreSettingsStore.h +++ b/Classes/LinphoneCoreSettingsStore.h @@ -30,6 +30,8 @@ - (void)transformLinphoneCoreToKeys; - (void)transformAccountToKeys:(NSString *)username; +- (void)transformLdapToKeys:(NSString *)ldap_server; - (void)removeAccount; +- (void)removeLdap; @end diff --git a/Classes/LinphoneCoreSettingsStore.m b/Classes/LinphoneCoreSettingsStore.m index 1203c80a2..b08f62311 100644 --- a/Classes/LinphoneCoreSettingsStore.m +++ b/Classes/LinphoneCoreSettingsStore.m @@ -257,6 +257,87 @@ } } + +- (void)transformLdapToKeys:(NSString *)ldap_server { + const MSList *ldaps = linphone_core_get_ldap_list(LC); + while (ldap_server && ldaps && + strcmp(ldap_server.UTF8String, + linphone_ldap_params_get_server(linphone_ldap_get_params(ldaps->data))) != 0) { + ldaps = ldaps->next; + } + LinphoneLdap *ldap = NULL; + + // default values + { + [self setBool:YES forKey:@"ldap_enabled"]; + [self setObject:@"" forKey:@"ldap_server"]; + [self setObject:@"" forKey:@"ldap_bind_dn"]; + [self setObject:@"" forKey:@"ldap_password"]; + [self setObject:@"simple" forKey:@"ldap_auth_method"]; + [self setBool:YES forKey:@"ldap_tls_enabled"]; + [self setObject:@"default" forKey:@"ldap_certificates_verification_mode"]; + [self setObject:@"" forKey:@"ldap_filter"]; + [self setInteger:50 forKey:@"ldap_max_results"]; + [self setInteger:5 forKey:@"ldap_timeout"]; + [self setInteger:500 forKey:@"ldap_delay"]; + [self setInteger:3 forKey:@"ldap_min_chars"]; + [self setObject:@"" forKey:@"ldap_name_attribute"]; + [self setObject:@"" forKey:@"ldap_sip_attribute"]; + [self setObject:@"" forKey:@"ldap_sip_domain"]; + [self setBool:NO forKey:@"ldap_logs_enabled"]; + } + + if (ldaps) { + ldap = ldaps->data; + LinphoneLdapParams const *ldapParams = linphone_ldap_get_params(ldap); + + int idx = (int)bctbx_list_index(linphone_core_get_ldap_list(LC), ldap); + [self setInteger:idx forKey:@"current_ldap_index"]; + + [self setBool:linphone_ldap_params_get_enabled(ldapParams) forKey:@"ldap_enabled"]; + [self setCString:linphone_ldap_params_get_server(ldapParams) forKey:@"ldap_server"]; + [self setCString:linphone_ldap_params_get_bind_dn(ldapParams) forKey:@"ldap_bind_dn"]; + [self setCString:linphone_ldap_params_get_password(ldapParams) forKey:@"ldap_password"]; + [self setBool:linphone_ldap_params_tls_enabled(ldapParams) forKey:@"ldap_tls_enabled"]; + + switch (linphone_ldap_params_get_auth_method(ldapParams)) { + case LinphoneLdapAuthMethodSimple: + [self setObject:@"simple" forKey:@"ldap_auth_method"]; + break; + case LinphoneLdapAuthMethodAnonymous: + [self setObject:@"anonymous" forKey:@"ldap_auth_method"]; + break; + } + + switch (linphone_ldap_params_get_server_certificates_verification_mode(ldapParams)) { + case LinphoneLdapCertVerificationDefault: + [self setObject:@"default" forKey:@"ldap_certificates_verification_mode"]; + break; + case LinphoneLdapCertVerificationEnabled: + [self setObject:@"enabled" forKey:@"ldap_certificates_verification_mode"]; + break; + case LinphoneLdapCertVerificationDisabled: + [self setObject:@"disabled" forKey:@"ldap_certificates_verification_mode"]; + break; + } + + [self setCString:linphone_ldap_params_get_base_object(ldapParams) forKey:@"ldap_base_object"]; + [self setCString:linphone_ldap_params_get_filter(ldapParams) forKey:@"ldap_filter"]; + [self setInteger:linphone_ldap_params_get_max_results(ldapParams) forKey:@"ldap_max_results"]; + [self setInteger:linphone_ldap_params_get_timeout(ldapParams) forKey:@"ldap_timeout"]; + [self setInteger:linphone_ldap_params_get_delay(ldapParams) forKey:@"ldap_delay"]; + [self setInteger:linphone_ldap_params_get_min_chars(ldapParams) forKey:@"ldap_min_chars"]; + + + [self setCString:linphone_ldap_params_get_name_attribute(ldapParams) forKey:@"ldap_name_attribute"]; + [self setCString:linphone_ldap_params_get_sip_attribute(ldapParams) forKey:@"ldap_sip_attribute"]; + [self setCString:linphone_ldap_params_get_sip_domain(ldapParams) forKey:@"ldap_sip_domain"]; + + bool ldapLogsEnabled = linphone_ldap_params_get_debug_level(ldapParams) == LinphoneLdapDebugLevelVerbose; + [self setBool:ldapLogsEnabled forKey:@"ldap_logs_enabled"]; + } +} + - (void)transformLinphoneCoreToKeys { LinphoneManager *lm = LinphoneManager.instance; @@ -424,6 +505,11 @@ [self setInteger:443 forKey:@"tunnel_port_preference"]; } } + + // contacts section + if (linphone_core_ldap_available(LC)) { + [self transformLdapToKeys:nil]; + } // advanced section { @@ -687,6 +773,71 @@ } } +- (void)synchronizeLdap { + LOGI(@"LDAP config changed, synchronizing."); + + LinphoneLdap*ldap = bctbx_list_nth_data(linphone_core_get_ldap_list(LC), [self integerForKey:@"current_ldap_index"]); + if (!ldap) { + return; + } + + if ([self stringForKey:@"ldap_base_object"].length == 0) { + UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Error", nil) + message:@"LDAPResearch base must not be empty" + preferredStyle:UIAlertControllerStyleAlert]; + + UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) {}]; + + [errView addAction:defaultAction]; + [PhoneMainView.instance presentViewController:errView animated:YES completion:nil]; + return; + } + + LinphoneLdapParams *newLdapParams = linphone_ldap_params_clone(linphone_ldap_get_params(ldap)); + + // Connexion parameters + linphone_ldap_params_set_enabled(newLdapParams, [self boolForKey:@"ldap_enabled"]); + linphone_ldap_params_set_server(newLdapParams, [self stringForKey:@"ldap_server"].UTF8String); + linphone_ldap_params_set_bind_dn(newLdapParams, [self stringForKey:@"ldap_bind_dn"].UTF8String); + linphone_ldap_params_set_password(newLdapParams, [self stringForKey:@"ldap_password"].UTF8String); + + LinphoneLdapAuthMethod authMethod = [[self stringForKey:@"ldap_verification_method"] isEqualToString:@"simple"] ? LinphoneLdapAuthMethodSimple : LinphoneLdapAuthMethodAnonymous; + linphone_ldap_params_set_auth_method(newLdapParams, authMethod); + linphone_ldap_params_enable_tls(newLdapParams, [self boolForKey:@"ldap_tls_enabled"]); + + + LinphoneLdapCertVerificationMode certVerifMode = LinphoneLdapCertVerificationDefault; + NSString *certVerifModeStr = [self stringForKey:@"ldap_certificates_verification_mode"]; + if ([certVerifModeStr isEqualToString:@"enabled"]) + certVerifMode = LinphoneLdapCertVerificationEnabled; + else if ([certVerifModeStr isEqualToString:@"disabled"]) + certVerifMode = LinphoneLdapCertVerificationEnabled; + linphone_ldap_params_set_server_certificates_verification_mode(newLdapParams, certVerifMode); + + // Research parameters + linphone_ldap_params_set_base_object(newLdapParams, [self stringForKey:@"ldap_base_object"].UTF8String); + linphone_ldap_params_set_filter(newLdapParams, [self stringForKey:@"ldap_filter"].UTF8String); + linphone_ldap_params_set_max_results(newLdapParams, [self integerForKey:@"ldap_max_results"]); + linphone_ldap_params_set_timeout(newLdapParams, [self integerForKey:@"ldap_timeout"]); + linphone_ldap_params_set_delay(newLdapParams, [self integerForKey:@"ldap_delay"]); + linphone_ldap_params_set_min_chars(newLdapParams, [self integerForKey:@"ldap_min_chars"]); + + + + // Analysis parameters + linphone_ldap_params_set_name_attribute(newLdapParams, [self stringForKey:@"ldap_name_attributes"].UTF8String); + linphone_ldap_params_set_sip_attribute(newLdapParams, [self stringForKey:@"ldap_sip_attributes"].UTF8String); + linphone_ldap_params_set_sip_domain(newLdapParams, [self stringForKey:@"ldap_sip_domain"].UTF8String); + + // Miscellaneous parameters + LinphoneLdapDebugLevel debugLevel = [self boolForKey:@"ldap_logs_enabled"] ? LinphoneLdapDebugLevelVerbose : LinphoneLdapDebugLevelOff; + linphone_ldap_params_set_debug_level(newLdapParams, debugLevel); + + linphone_ldap_set_params(ldap, newLdapParams); +} + - (BOOL)synchronize { @try { LinphoneManager *lm = LinphoneManager.instance; @@ -705,7 +856,7 @@ if (account_changed) [self synchronizeAccounts]; - + bool enableVideo = [self boolForKey:@"enable_video_preference"]; linphone_core_enable_video_capture(LC, enableVideo); linphone_core_enable_video_display(LC, enableVideo); @@ -911,6 +1062,19 @@ linphone_tunnel_set_mode(tunnel, mode); } + // contacts section + + + BOOL ldap_changed = NO; + for (NSString *key in self->changedDict) { + if ([key hasPrefix:@"ldap_"] && [self valueChangedForKey:key]) { + ldap_changed = YES; + break; + } + } + if (ldap_changed) + [self synchronizeLdap]; + // advanced section BOOL animations = [self boolForKey:@"animations_preference"]; [lm lpConfigSetInt:animations forKey:@"animations_preference"]; @@ -1012,4 +1176,11 @@ } [self transformLinphoneCoreToKeys]; } + +- (void)removeLdap { + LinphoneLdap *ldap = bctbx_list_nth_data(linphone_core_get_ldap_list(LC), + [self integerForKey:@"current_ldap_index"]); + linphone_core_remove_ldap(LC, ldap); + [self transformLinphoneCoreToKeys]; +} @end diff --git a/Classes/SettingsView.m b/Classes/SettingsView.m index 4064de1fb..86954998b 100644 --- a/Classes/SettingsView.m +++ b/Classes/SettingsView.m @@ -592,7 +592,33 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat [specifier.specifierDict setValue:name forKey:kIASKTitle]; } } - + + if ([specifier.key hasPrefix:@"ldap_"]) { + if (linphone_core_ldap_available(LC)) { + const bctbx_list_t *ldaps = linphone_core_get_ldap_list(LC); + int index = [specifier.key substringFromIndex:@"ldap_".length].intValue - 1; + if (index < bctbx_list_size(ldaps)) { + const LinphoneLdapParams *ldapParams = linphone_ldap_get_params(bctbx_list_nth_data(ldaps, index)); + + NSString *name = [NSString + stringWithUTF8String:linphone_ldap_params_get_server(ldapParams)]; + [specifier.specifierDict setValue:name forKey:kIASKTitle]; + } + } + } + + + if ([[specifier key] isEqualToString:@"ldap_auth_method"]) { + NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary:[specifier specifierDict]]; + NSMutableArray *titles = [NSMutableArray arrayWithArray:[dict objectForKey:@"Titles"]]; + [titles removeObject:@"TLS"]; + [dict setObject:titles forKey:@"Titles"]; + NSMutableArray *values = [NSMutableArray arrayWithArray:[dict objectForKey:@"Values"]]; + [values removeObject:@"tls"]; + [dict setObject:values forKey:@"Values"]; + return [[IASKSpecifier alloc] initWithSpecifier:dict]; + } + return specifier; } @@ -605,10 +631,17 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat [hiddenKeys addObject:[NSString stringWithFormat:@"menu_account_%lu", i]]; } + const MSList *ldaps = linphone_core_get_ldap_list(LC); + for (size_t i = bctbx_list_size(ldaps) + 1; i <= 5; i++) { + [hiddenKeys addObject:[NSString stringWithFormat:@"ldap_%lu", i]]; + } if (!linphone_core_sip_transport_supported(LC, LinphoneTransportTls)) { [hiddenKeys addObject:@"media_encryption_preference"]; } + if (!linphone_core_ldap_available(LC)) { + [hiddenKeys addObject:@"contacts_menu"]; + } #ifndef DEBUG [hiddenKeys addObject:@"debug_actions_group"]; [hiddenKeys addObject:@"release_button"]; @@ -743,6 +776,17 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat [[_settingsController tableView] reloadData]; } +-(void)recomputeLdapLabelsAndSync { + // it's a bit violent... but IASK is not designed to dynamically change subviews' name + _settingsController.hiddenKeys = [self findHiddenKeys]; + [_settingsController.settingsReader indexPathForKey:@"ldap_1"]; // force refresh ldap server name display + [_settingsController.settingsReader indexPathForKey:@"ldap_2"]; // force refresh ldap server name display + [_settingsController.settingsReader indexPathForKey:@"ldap_3"]; // force refresh ldap server name display + [_settingsController.settingsReader indexPathForKey:@"ldap_4"]; // force refresh ldap server name display + [_settingsController.settingsReader indexPathForKey:@"ldap_5"]; // force refresh ldap server name display + [[_settingsController tableView] reloadData]; +} + #pragma mark - IASKSettingsDelegate Functions - (void)settingsViewControllerDidEnd:(IASKAppSettingsViewController *)sender { @@ -754,10 +798,15 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat // going to account: fill account specific info if ([sender.file isEqualToString:@"Account"]) { - LOGI(@"Going editting account %@", sender.title); + LOGI(@"Going editing account %@", sender.title); [settingsStore transformAccountToKeys:sender.title]; - // coming back to default: if we were in account, we must synchronize account now - } else if ([sender.file isEqualToString:@"Root"]) { + } else if ([sender.file isEqualToString:@"Contacts"]) { + [settingsStore synchronize]; + [self recomputeLdapLabelsAndSync]; + } else if ([sender.file isEqualToString:@"LDAP"]) { + LOGI(@"Going editing LDAP config %@", sender.title); + [settingsStore transformLdapToKeys:sender.title]; + } else if ([sender.file isEqualToString:@"Root"]) { // coming back to default: if we were in account, we must synchronize account now [settingsStore synchronize]; [self recomputeAccountLabelsAndSync]; } @@ -987,6 +1036,32 @@ void update_hash_cbs(LinphoneAccountCreator *creator, LinphoneAccountCreatorStat [self presentViewController:errView animated:YES completion:nil]; } else if ([key isEqual:@"send_db_button"]) { [self sendEmailWithPrivacyAttachments]; + } else if ([key isEqual:@"new_ldap_button"]) { + if (bctbx_list_size(linphone_core_get_ldap_list(LC)) < 5 ) { + linphone_core_add_ldap(LC, linphone_core_create_ldap(LC)); + [self recomputeLdapLabelsAndSync]; + } + } else if ([key isEqual:@"ldap_remove_button"]) { + UIAlertController *errView = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Warning", nil) + message:NSLocalizedString(@"Are you sure to want to remove your LDAP config?", nil) + preferredStyle:UIAlertControllerStyleAlert]; + + UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) {}]; + + UIAlertAction* continueAction = [UIAlertAction actionWithTitle:NSLocalizedString(@"Yes", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + [settingsStore removeLdap]; + [self recomputeLdapLabelsAndSync]; + [_settingsController.navigationController popViewControllerAnimated:NO]; + }]; + + + [errView addAction:defaultAction]; + [errView addAction:continueAction]; + [self presentViewController:errView animated:YES completion:nil]; } } diff --git a/Settings/InAppSettings.bundle/Contacts.plist b/Settings/InAppSettings.bundle/Contacts.plist new file mode 100644 index 000000000..4bba4dfc3 --- /dev/null +++ b/Settings/InAppSettings.bundle/Contacts.plist @@ -0,0 +1,73 @@ + + + + + PreferenceSpecifiers + + + Title + LDAP configs + Type + PSGroupSpecifier + + + Key + new_ldap_button + Title + Add new LDAP config (5 max) + Type + IASKButtonSpecifier + + + Key + ldap_1 + File + LDAP + Title + LDAP 1 + Type + PSChildPaneSpecifier + + + Key + ldap_2 + File + LDAP + Title + LDAP 2 + Type + PSChildPaneSpecifier + + + Key + ldap_3 + File + LDAP + Title + LDAP 3 + Type + PSChildPaneSpecifier + + + Key + ldap_4 + File + LDAP + Title + LDAP 4 + Type + PSChildPaneSpecifier + + + Key + ldap_5 + File + LDAP + Title + LDAP 5 + Type + PSChildPaneSpecifier + + + + diff --git a/Settings/InAppSettings.bundle/LDAP.plist b/Settings/InAppSettings.bundle/LDAP.plist new file mode 100644 index 000000000..f1658bd04 --- /dev/null +++ b/Settings/InAppSettings.bundle/LDAP.plist @@ -0,0 +1,318 @@ + + + + + PreferenceSpecifiers + + + Type + PSToggleSwitchSpecifier + Title + Enabled + Key + ldap_enabled + DefaultValue + + + + Key + ldap_remove_button + Title + Delete this LDAP config + Type + IASKButtonSpecifier + + + Title + Connexion + Type + PSGroupSpecifier + + + Key + ldap_server + Title + Server URL + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + DefaultValue + + IASKTextAlignment + IASKUITextAlignmentRight + + + Key + ldap_bind_dn + Title + Bind DN + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + DefaultValue + + IASKTextAlignment + IASKUITextAlignmentRight + + + IASKTextAlignment + IASKUITextAlignmentRight + AutocapitalizationType + None + AutocorrectionType + No + DefaultValue + + IsSecure + + Key + lda^p + KeyboardType + Alphabet + Title + Password + Type + PSTextFieldSpecifier + + + DefaultValue + simple + Key + ldap_auth_method + Title + Authentication Method + Titles + + Simple + Anonymous + + Type + PSMultiValueSpecifier + Values + + simple + anonymous + + + + Type + PSToggleSwitchSpecifier + Title + Use TLS + Key + ldap_tls_enabled + DefaultValue + + + + DefaultValue + simple + Key + ldap_certificates_verification_mode + Title + Certificate Verification + Titles + + Auto + Enabled + Disabled + + Type + PSMultiValueSpecifier + Values + + default + enabled + disabled + + + + Title + Research + Type + PSGroupSpecifier + + + Key + ldap_base_object + Title + Research Base + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + DefaultValue + + IASKTextAlignment + IASKUITextAlignmentRight + + + Key + ldap_filter + Title + Filter + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + DefaultValue + + IASKTextAlignment + IASKUITextAlignmentRight + + + Key + ldap_max_results + Title + Max results + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + KeyboardType + NumberPad + DefaultValue + 50 + IASKTextAlignment + IASKUITextAlignmentRight + + + Key + ldap_timeout + Title + Timeout (seconds) + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + KeyboardType + NumberPad + DefaultValue + 5 + IASKTextAlignment + IASKUITextAlignmentRight + + + Key + ldap_delay + Title + Delay (milliseconds) + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + KeyboardType + NumberPad + DefaultValue + 500 + IASKTextAlignment + IASKUITextAlignmentRight + + + Key + ldap_min_chars + Title + Min chars + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + KeyboardType + NumberPad + DefaultValue + 3 + IASKTextAlignment + IASKUITextAlignmentRight + + + + Title + Analysis + Type + PSGroupSpecifier + + + Key + ldap_name_attribute + Title + Name Attributes + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + DefaultValue + + IASKTextAlignment + IASKUITextAlignmentRight + + + Key + ldap_sip_attribute + Title + SIP Attributes + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + DefaultValue + + IASKTextAlignment + IASKUITextAlignmentRight + + + Key + ldap_sip_domain + Title + Domain + Type + PSTextFieldSpecifier + AutocapitalizationType + None + AutocorrectionType + No + DefaultValue + + IASKTextAlignment + IASKUITextAlignmentRight + + + Title + Miscellaneous + Type + PSGroupSpecifier + + + Type + PSToggleSwitchSpecifier + Title + Enabled + Key + ldap_logs_enabled + DefaultValue + + + + + diff --git a/Settings/InAppSettings.bundle/Root.plist b/Settings/InAppSettings.bundle/Root.plist index 2fbc0eab4..b4c5a2cec 100644 --- a/Settings/InAppSettings.bundle/Root.plist +++ b/Settings/InAppSettings.bundle/Root.plist @@ -144,6 +144,16 @@ Type PSChildPaneSpecifier + + Key + contacts_menu + File + Contacts + Title + Contacts + Type + PSChildPaneSpecifier + File Advanced