Integrating LogglyLogger-CocoaLumberjack in swift project - ios

I am trying to use LogglyLogger-CocoaLumberjack in my swift project.
I am getting this error in xCode.
Enum case 'verbose' has no associated values
I am unable to resolve this.
https://prnt.sc/uznr01
I am actually trying to translate the Objective-C code in swift 5. Here is my swift function
in appDelegate.swift class
func initLoggly(){
// static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
let ddLogLevel:DDLogLevel = .verbose
// LogglyLogger *logglyLogger = [[LogglyLogger alloc] init];
let logglyLogger = LogglyLogger()
// [logglyLogger setLogFormatter:[[LogglyFormatter alloc] init]];
logglyLogger.logFormatter = LogglyFormatter()
// logglyLogger.logglyKey = #"your-loggly-api-key";
logglyLogger.logglyKey = "XXXXXXXXXXXX-XXXXXX"
//
// // Set posting interval every 15 seconds, just for testing this out, but the default value of 600 seconds is better in apps
// // that normally don't access the network very often. When the user suspends the app, the logs will always be posted.
// logglyLogger.saveInterval = 15;
logglyLogger.saveInterval = 15
// [DDLog addLogger:logglyLogger];
DDLog.add(logglyLogger)
// // Do some logging
// DDLogVerbose(#"{\"myJsonKey\":\"some verbose json value\"}");
// ddLogLevel.verbose("{\"initloggly\":\"some verbose json value\"}") // also tried this, error ==> Enum case 'verbose' cannot be used as an instance member
DDLogLevel.verbose("{\"initloggly\":\"some verbose json value\"}") // Here is the error on this line
}
Please point out what I am doing wrong!

This library is heavly based on C preprocessor macros which aren't accessible from Swift.
You will probably need to write a small set of wrapper functions in Objective-C that use these macros and are in turn callable from Swift.
Here's an example of how this could look like:
LogglyWrapper.h:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#interface LogglyWrapper : NSObject
+(void) logVerbose:(NSString*) msg;
#end
NS_ASSUME_NONNULL_END
and LogglyWrapper.m:
#import "LogglyWrapper.h"
#import <LogglyLogger.h>
#implementation LogglyWrapper
static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
+(void) logVerbose:(NSString*) msg {
DDLogVerbose(#"%#", msg);
}
#end
usage from Swift:
LogglyWrapper.logVerbose("foo")

Related

iOS - swift - Generating key pair for secp224k1 curve (ECDH)

I have been trying to generate public and private keys for the secp224k1 curve in iOS. We are using ECDH method to do api handshake between mobile and backend. In Java it is done using the below code.
public static KeyPair getECKeyPair() throws NoSuchProviderException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {
ECGenParameterSpec ecSpec = new ECGenParameterSpec("secp224k1");
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECDH", "SC");
kpg.initialize(ecSpec);
return kpg.generateKeyPair();
}
Is there a way to generate keys with the specific curve(secp224k1) type in swift? I tried using the apple provided EC algorithm to do the handshake by using the below code.
//Generates public and private key with EC algorithm
public static func getKey() -> [String: SecKey]? {
let attributes: [String: Any] =
[kSecAttrKeySizeInBits as String: 256,
kSecAttrKeyType as String: kSecAttrKeyTypeEC,
kSecPrivateKeyAttrs as String:
[kSecAttrIsPermanent as String: false]
]
var error: Unmanaged<CFError>?
guard let privateKey = SecKeyCreateRandomKey(attributes as CFDictionary, &error) else {
let err = error!.takeRetainedValue() as Error
print(err.localizedDescription)
return nil
}
guard let publicKey = SecKeyCopyPublicKey(privateKey) else {
print("Error occured while creating public key")
return nil
}
return ["publicKey": publicKey, "privateKey": privateKey]
}
When I send the public key generated via above method I get an error from server with a message:
"error":"java.security.InvalidKeyException: ECDH key agreement requires ECPublicKey for doPhase","exception":"InvalidAuthException"
I tried VirgilCrypto for swift which came close to solving the problem. But it doesn't have the specific curve type in the library which I need. It has support for secp256r1 only. Also, answers from the below posts I tried and didn't work out.
Elliptic Curve Diffie Hellman in ios/swift
Any suggestions or help would be great, Thanks.
The Koblitz 224-bit curve is not supported by iOS. One solution might be to use a different curve type or a third-party library with secp224k1 support.
From your comments it can be concluded that the secp224k1 curve type is a requirement.
A third-party library that might be used is Virgil Crypto, which is available through github https://github.com/VirgilSecurity/virgil-crypto. It is a C++ library. (Virgil Security is also offering a Swift wrapper lib called virgil-crypto-x, but that one no longer supports secp224k1 in the current version).
C++ libs can be used in Swift indirectly by creating a Objective-C++ wrapper with a defined interface.
Build VSCCrypto.framework
On the command line enter:
git clone https://github.com/VirgilSecurity/virgil-crypto
cd virgil-crypto
utils/build.sh --target=ios
This builds the framework for iOS.
Add VSCCrypto.framework to Xcode Project
select root node in project navigator
in Xcode create 'New Group'
name it 'Frameworks'
drag & drop in Finder the VSCCrypto.framework in the folder virgil-crypto/build/ios/lib to the 'Frameworks' group
in XCode on the right under 'Embedded Binaries' tap plus
select the VSCCrypto.framework
Objective-C++ Wrapper
create a ECDHCrypto Objective-C file
when asked for 'Would you like to configure an Objective-C bridging header' tap on 'Create Bridging Header'
in the project navigator change the file suffix from .m to .mm (to allow C++ code there)
add #import "ECDHCrypto.h" to the bridging header
ECDHCrypto.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#interface ECDHCrypto : NSObject
#property(nonatomic, strong) NSString *ownPrivateKey;
#property(nonatomic, strong) NSString *ownPublicKey;
- (void)generateKeyPair;
- (NSString *)shared:(NSString *)otherPublicKey;
#end
NS_ASSUME_NONNULL_END
ECDHCrypto.mm
#import "ECDHCrypto.h"
#import <VSCCrypto/VirgilCrypto.h>
using virgil::crypto::VirgilKeyPair;
using virgil::crypto::VirgilByteArray;
using virgil::crypto::VirgilCipherBase;
using virgil::crypto::str2bytes;
using virgil::crypto::bytes2str;
using virgil::crypto::bytes2hex;
#implementation ECDHCrypto
- (void)generateKeyPair {
VirgilKeyPair keyPair = VirgilKeyPair::generate(VirgilKeyPair::Type::EC_SECP224K1);
VirgilByteArray ownPublicKeyBates = keyPair.publicKey();
self.ownPublicKey = [NSString stringWithCString:bytes2str(ownPublicKeyBates).c_str()
encoding:[NSString defaultCStringEncoding]];
VirgilByteArray ownPrivateKeyBytes = keyPair.privateKey();
self.ownPrivateKey = [NSString stringWithCString:bytes2str(ownPrivateKeyBytes).c_str()
encoding:[NSString defaultCStringEncoding]];
}
- (NSString *)shared:(NSString *)otherPublicKey {
NSAssert(self.ownPrivateKey, #"private key must be set, e.g. use generateKeyPair");
std::string otherPKString([otherPublicKey cStringUsingEncoding:NSASCIIStringEncoding]);
VirgilByteArray pubKey = str2bytes(otherPKString);
std::string ownPrivateKeyString([self.ownPrivateKey cStringUsingEncoding:NSASCIIStringEncoding]);
VirgilByteArray ownPrivateKeyBytes = str2bytes(ownPrivateKeyString);
VirgilByteArray shared_ba = VirgilCipherBase::computeShared(pubKey, ownPrivateKeyBytes);
std::string hex = bytes2hex(shared_ba);
NSString *shared = [NSString stringWithCString:hex.c_str()
encoding:[NSString defaultCStringEncoding]];
return shared;
}
#end
Usage in Swift
let otherPK = """
-----BEGIN PUBLIC KEY-----
ME4wEAYHKoZIzj0CAQYFK4EEACADOgAEgeW/foqxCDOd1y6lnXONkRThS6xhjLHP
SEXs7jHSpoaPQH4vArcGmIb1cAZcepEh7WDQxCyfQXg=
-----END PUBLIC KEY-----
"""
let ecdhCrypto = ECDHCrypto()
ecdhCrypto.generateKeyPair();
print("ecdhCrypto.ownPublicKey: \n" + ecdhCrypto.ownPublicKey);
print("shared secret: " + ecdhCrypto.shared(otherPK));
Test With Java Counterpart
To test whether a key exchange is successful, one can perform the following test:
In Java, a secp224k1 key pair is generated and the public key is output to the console.
The public key is copied into the Swift code of an iOS application using Copy/Paste. The app then generates a key pair and writes its own public key to the console, as well as the calculated shared secret. The iOS public key is then inserted into the Java program as an input (displayed in green).
Finally, one can compare the shared secret of the iOS app and the Java program. Here it is the same, so the key exchange was successful.
In the upper area you see Xcode with the iOS source code and in the lower area the output of the Java program:

ios Native webrtc : How to record remote audio stream as wav file on client side.

I am experimenting on webrtc, My goal is to store remote audio stream as a local file without using the media server, I am aware of aecdump but I don't find proper method or blog to unzip in iOS.
I am using googleWebrtc native framework.
Thanks.
Yes First to get the IOS directory path you must have to create your own objective c file.
my_ios_wav.mm
#import <Foundation/Foundation.h>
#include <string.h>
#import "sdk/objc/helpers/NSString+StdString.h"
#include "rtc_base/checks.h"
namespace webrtc{
std::string myIOSPath() {
#autoreleasepool {
NSString* tempDir = NSTemporaryDirectory();
if (tempDir == nil)
tempDir = #"/tmp";
return [NSString stdStringForString:tempDir];
}
}
}
After that create a static function in the class you have data that you want to record.
static webrtc::WavWriter* my_funtion()
{
const std::string outfilewav = webrtc::myIOSPath() + "wavtest1.wav";
static webrtc::WavWriter *my_wav_pointer(new
webrtc::WavWriter(outfilewav, 48000,1,webrtc::WavFile::SampleFormat::kInt16));
return my_wav_pointer;
}
After that call this static function where you want to pass the data to wav file for recording like:
my_funtion()->WriteSamples(audio_frame->data(), number_of_frames);

Can i change the server url with sudzc?

I am trying to generate source code from a wsdl file for iOS. I've stumbled upon a couple of tools and so far wsclient++ and sudzc at least seem to work. But I need to send requests to different servers with the same soap interface, depending on the state of the iOS app.
In the source code generated by wsclient I can set the server URL via
MyWebService* ws = [MyWebService service];
// // set base url for entire application
[SoapWebService setGlobalBaseUrl: #"http://domain.com"];
NSError* error = nil;
Result* rs = [ws callMethod: p1 param2:p2 error:&error];
Which would me allow me to do something like
if(condition1) [SoapWebService setGlobalBaseUrl: #"http://betaserver.com"];
if(condition2) [SoapWebService setGlobalBaseUrl: #"http://developserver.com"];
if(condition3) [SoapWebService setGlobalBaseUrl: #"http://liveserver.com"];
Is there a way to archive something similar with the source code generated by sudzc?
As long as the soap is the same response you shouldn't have a problem using your code. There is a file that stores the server address. The code generated by sudzc can be modified to any address. I actually created a dynamic way of hitting servers. I will find the file and code I used to do this.
You can search the project for your domain you used for sudzc.
I'm not in front of a mac right now, but I will update later.
UPDATE:
Ok, so I created a settings tab and allowed the user to input a specific ip address if necessary. It saves the IP address in a dictionary and then this file retrieves it from the dictionary. I left some of my original comments and added some in the code so you can see both ways. If it confuses you let me know and I'll edit again. In my sudzc generated code I modified the file to this:
/*
wsUpdateQOH.m
The implementation classes and methods for the wsUpdateQOH web service.
Generated by SudzC.com
*/
#import "wsUpdateQOH.h"
#import "Soap.h"
#import "Settings.h"
#define URL #"http://%#/webServiceAddress/updateqoh.asmx"
/* Implementation of the service */
#implementation wsUpdateQOH
- (id) init
{
if(self = [super init])
{
// take out hard coded address and add variable to have a dynamic IP #"http://www.site.com/webServiceAddress/updateqoh.asmx"
// here is the dictionary return and format of the url string
NSString *savedValue = [[NSUserDefaults standardUserDefaults] stringForKey:#"serverIP"];
self.serviceUrl = [[NSString alloc] initWithFormat:URL, savedValue];
// uncomment for a hard coded address self.serviceUrl = #"http://%#/webServiceAddress/updateqoh.asmx";
self.namespace = #"http://tempuri.org/webServiceAddress/UpdateQOH";
self.headers = nil;
self.logging = NO;
}
return self;
}
- (id) initWithUsername: (NSString*) username andPassword: (NSString*) password {
if(self = [super initWithUsername:username andPassword:password]) {
}
return self;
}
+ (wsUpdateQOH*) service {
return [wsUpdateQOH serviceWithUsername:nil andPassword:nil];
}
+ (wsUpdateQOH*) serviceWithUsername: (NSString*) username andPassword: (NSString*) password {
return [[[wsUpdateQOH alloc] initWithUsername:username andPassword:password] autorelease];
}
// *** Below here is the soap actions ***

IOS self->isa deprecated but Object_setClass also gives a warning

I'm busy with a library of a collegae. In his code he sets isa a few times. This stills works but is officially deprecated. The alternative should be the object_setClass function. But when I replace it I get a warning: Implicit declaration of function 'object_setClass' is invalid in C99.
Perhaps i am missing an import or something? Anyone an idea? Thanks.
if(nodePtr->type == XML_ELEMENT_NODE)
{
self->isa = [DDXMLElement class];
//object_setClass(self, [DDXMLElement class]);
}
else if(nodePtr->type == XML_DOCUMENT_NODE)
{
self->isa = [DDXMLDocument class];
//object_setClass(self, [DDXMLDocument class]);
}
It's declared in #include <objc/runtime.h> -- have you included that header?

Conditional IF/ELSE statements in iOS Constants File

Fellow Coders...
I have server url's set up in my application's global constants file.
I also have a variable called "DebugMode" in my application plist that once switched should change the urls the application will be using.
Constants.h
extern NSString * const LOGIN_URL;
Constants.m
NSString * const LOGIN_URL = #"http://www.url.com";
Anyway I can replicate the following psuedo code below into Objective C?
if([[[[NSBundle mainBundle] infoDictionary] objectForKey:#"DebugMode"] boolValue] == NO)
{
NSString * const LOGIN_URL = #"http://www.production-url.com";
}
else
{
NSString * const LOGIN_URL = #"http://www.qa-url.com";
}
What your asking for isn't exactly possible (at least not in the way your asking for). A constant is setup and established whilst compiling (not strictly true, but for the sake of this explanation, it will do) and thus means that it can not be mutated for any reason at runtime.
The traditional way of changing the values of constants depending on debug and release code is through the preprocessor. Like so:
#if __DEBUG_MODE__ == 1
NSString * const LOGIN_URL = #"http://www.qa-url.com";
#else
NSString * const LOGIN_URL = #"http://www.production-url.com";
#endif
Now __DEBUG_MODE__ needs to be defined before it can do anything, and there are a few ways you could do this. You could add the following line to you prefix header file (.pch)
#define __DEBUG_MODE__ 1 // Change to 0 to disable debug mode.
or add the compiler flag -M__DEBUG_MODE__=1 to the file you wish to effect. This means that whenever __DEBUG_MODE__ is set with a value of 1, the compiler will use your debug constant, and when it has a value of 0 the compiler will use the production constant.
This also has the benefit of keeping debug and production code separate (you should avoid having both in your binary as it can open a whole world of problems and security issues).
Hope this helps.
Whenever I've had a situation like this I've just created a class method in my constants file:
+ (NSString *)loginURL {
if([[[[NSBundle mainBundle] infoDictionary] objectForKey:#"DebugMode"] boolValue] == NO){
return #"http://www.production-url.com";
}
else {
return #"http://www.qa-url.com";
}
}
It also makes it more clear in your code that as the loginURL string is coming via a method, it may be dependent on a run time condition:
NSURL *loginURL = [NSURL URLWithString:[Constants loginURL]];

Resources