Convert raw image data to base64 encoded string - ios

I am downloading a thumbnail from dropbox using the following API:
https://www.dropbox.com/developers/documentation/http/documentation#files-get_thumbnail
This is part of my function from cloud code:
}).then(function(oauthToken){
/* Retrieve thumbnail image from dropbox */
return Parse.Cloud.httpRequest({
method: 'POST',
url: 'https://content.dropboxapi.com/2/files/get_thumbnail',
headers: {
'Authorization': 'Bearer ' + oauthToken.get("accessToken"),
'Dropbox-API-Arg': JSON.stringify({"path": dropboxFileId})
}
});
}).then(function(imageResponse){
if (log) {console.log(imageResponse);}
var imageBuffer = imageResponse.buffer;
var image = imageBuffer.toString("base64");
response.success(image);
}, function(error){
response.error(error.text);
});
Following is my imageResponse:
{ status: 200,
headers:
{ server: 'nginx',
date: 'Wed, 16 Mar 2016 04:30:54 GMT',
'content-type': 'application/octet-stream',
'content-length': '906',
connection: 'close',
'accept-ranges': 'bytes',
pragma: 'no-cache',
'cache-control': 'no-cache',
'original-content-length': '906',
'dropbox-api-result': '{"name": "HTS-logo-low-res.png", "path_lower": "/hts-logo-low-res.png", "path_display": "/HTS-logo-low-res.png", "id": "id:hrkr_mV5FYAAAAAAAAAAHw", "client_modified": "2015-04-05T04:16:15Z", "server_modified": "2016-02-13T06:08:02Z", "rev": "2a043d0c726", "size": 10506}',
'x-server-response-time': '190',
'x-dropbox-request-id': '04bb8d6b45511f2b2d7a278e230ea572',
'x-robots-tag': 'noindex, nofollow, noimageindex' },
buffer: <Buffer ef bf bd ef bf bd ef bf bd ef bf bd 00 10 4a 46 49 46 00 01 01 00 00 01 00 01 00 00 ef bf bd ef bf bd 00 43 00 06 04 05 06 05 04 06 06 05 06 07 07 06 ... >,
cookies: undefined,
text: '����\u0000\u0010JFIF\u0000\u0001\u0001\u0000\u0000\u0001\u0000\u0001\u0000\u0000��\u0000C\u0000\u0006\u0004\u0005\u0006\u0005\u0004\u0006\u0006\u0005\u0006\u0007\u0007\u0006\b\n\u0010\n\n\t\t\n\u0014\u000e\u000f\f\u0010\u0017\u0014\u0018\u0018\u0017\u0014\u0016\u0016\u001a\u001d%\u001f\u001a\u001b#\u001c\u0016\u0016 , #&\')*)\u0019\u001f-0-(0%()(��\u0000C\u0001\u0007\u0007\u0007\n\b\n\u0013\n\n\u0013(\u001a\u0016\u001a((((((((((((((((((((((((((((((((((((((((((((((((((��\u0000\u0011\b\u0000\u0010\u0000#\u0003\u0001"\u0000\u0002\u0011\u0001\u0003\u0011\u0001��\u0000\u001f\u0000\u0000\u0001\u0005\u0001\u0001\u0001\u0001\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b��\u0000�\u0010\u0000\u0002\u0001\u0003\u0003\u0002\u0004\u0003\u0005\u0005\u0004\u0004\u0000\u0000\u0001}\u0001\u0002\u0003\u0000\u0004\u0011\u0005\u0012!1A\u0006\u0013Qa\u0007"q\u00142���\b#B��\u0015R��$3br�\t\n\u0016\u0017\u0018\u0019\u001a%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz���������������������������������������������������������������������������\u0000\u001f\u0001\u0000\u0003\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0001\u0000\u0000\u0000\u0000\u0000\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b��\u0000�\u0011\u0000\u0002\u0001\u0002\u0004\u0004\u0003\u0004\u0007\u0005\u0004\u0004\u0000\u0001\u0002w\u0000\u0001\u0002\u0003\u0011\u0004\u0005!1\u0006\u0012AQ\u0007aq\u0013"2�\b\u0014B����\t#3R�\u0015br�\n\u0016$4�%�\u0017\u0018\u0019\u001a&\'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz��������������������������������������������������������������������������\u0000\f\u0003\u0001\u0000\u0002\u0011\u0003\u0011\u0000?\u0000�;ŷ��鱘\'[s,�\u0013L�\n���{\f�g޹\u000f��I�\\.�w\u0013��H~̡���\u0002�\u001b���\u000f\u0001���#�%�&�O��\u0004z����6�Z:X�"G;�GB}M%N�3��ͧ]4��̪��9`�������0�֕�+\u000b�t \u0006P�\u0001%�z��\u0003�R=ި�G$.� �U��h]���d�\u001d9����u���*O����q��|�\u0007\u0005\\�N\u000e\u0017\u0003�\u0000C�q��;�K���1\u001e��HR��z��~�N+���uy��d�بS咕�0e��91�\u001fC�\u0014���}z����.u\u0019Y�I\u0012�T.�\u0019~�\u0007ߦ\b��+���ߝ��W���_q��'
}
My code in XCode:
if let imageInBase64 = response as? String {
print(imageInBase64)
let decodedImage = NSData(base64EncodedString: imageInBase64, options: NSDataBase64DecodingOptions())
imageView.image = UIImage(data: decodedImage!)
}
Following is the output for imageInBase64:
77+977+977+977+9ABBKRklGAAEBAAABAAEAAO+/ve+/vQBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSjvv73vv70AQwEHBwcKCAoTCgoTKBoWGigoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo77+977+9ABEIABAAQAMBIgACEQEDEQHvv73vv70AHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL77+977+9AO+/vRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDLvv73vv73vv70II0Lvv73vv70VUu+/ve+/vSQzYnLvv70JChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl677+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+977+9AB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC++/ve+/vQDvv70RAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjLvv70IFELvv73vv73vv73vv70JIzNS77+9FWJy77+9ChYkNO+/vSXvv70XGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eu+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/ve+/vQAMAwEAAhEDEQA/AO+/vTvFt++/ve+/vemxmCdbcyzvv70TTO+/vQrvv73vv73vv717DO+/vWfeuX8P77+977+9Se+/vVwu77+9dxPvv73vv71Ifsyh77+977+977+9Au+/vRvvv73vv73vv70PAe+/ve+/ve+/vUDvv70l77+9Ju+/vU/vv73vv70Eeu+/ve+/ve+/ve+/vTbvv71aOljvv70iRzvvv71HQn1NJU7vv70z77+977+9zaddNO+/ve+/vcyq77+977+9OWDvv73vv73vv73vv73vv73vv73vv70w77+91pXvv70rC++/vXQgBlDvv70BJe+/vXrvv73vv70D77+9Uj3eqO+/vUckLu+/vSDvv71V77+977+9aF3vv73vv73vv71k77+9HTnvv73vv73vv73vv71177+977+977+9Kk/vv73vv73vv73vv71x77+977+9fO+/vQcFXO+/vU4OFwPvv70AQ++/vXHvv73vv70777+9S++/ve+/ve+/vTEe77+977+9SFLvv73vv71677+977+9fu+/vU4r77+977+977+9dXnvv73vv71k77+92KhT5ZKV77+9MGXvv73vv705Me+/vR9D77+9FO+/ve+/ve+/vX1677+977+977+977+9LnUZWe+/vUkS77+9VC7vv70Zfu+/vQffpgjvv73vv70r77+977+977+9353vv73vv71X77+977+977+9X3Hvv73vv70=
When I run this, I do not get an image displayed. I suspect that I am not properly handling the response from Dropbox before converting it to base64 string. Dropbox state that their responses are raw image data.
Any help will be much appreciated. Thanks.

Figured it out & thanks for those who answered. The issue was with Parse.com module Parse.Cloud.httpRequest which works slightly different when you are self-hosting parse-server vs Parse.com. I just needed to include encoding: null as an option in the module and everything works fine. Code below:
}).then(function(oauthToken){
/* Retrieve thumbnail image from dropbox */
return Parse.Cloud.httpRequest({
method: 'POST',
url: 'https://content.dropboxapi.com/2/files/get_thumbnail',
headers: {
'Authorization': 'Bearer ' + oauthToken.get("accessToken"),
'Dropbox-API-Arg': JSON.stringify({"path": dropboxFileId})
},
encoding: null
});
}).then(function(imageResponse){
if (log) {console.log(imageResponse);}
var imageBuffer = imageResponse.buffer;
var image = imageBuffer.toString("base64");
response.success(image);
}, function(error){
response.error(error.text);
});

Related

GraphicsMagick .toBuffer() creates empty buffer stream

I have a Firebase Cloud Function that converts a buffer (from PDF) to a PNG using GraphcisMagick. When I attempt to write this PNG buffer to Firebase Storage, I get a file stub but no content (empty file). My conversion to PNG is failing...
async function createThumbnail(newthumbname, mimetype, filebuffer) {
const file = bucket.file(newthumbname)
const thumbstream = file.createWriteStream({metadata:{contentType:mimetype}})
const gm = require('gm').subClass({imageMagick: true})
gm(filebuffer)
.toBuffer('png', (err, thumbbuffer)=>{
console.log(filebuffer)
console.log(thumbbuffer)
thumbstream.end(thumbbuffer)
})
}
The filebuffer passed into the createThumbnail() has content,
<Buffer 25 50 44 46 2d 31 2e 33 0a 25 c4 e5 f2 e5 eb a7 f3 a0 d0 c4 c6 0a 33 20 30 20 6f 62 6a 0a 3c 3c 20 2f 46 69 6c 74 65 72 20 2f 46 6c 61 74 65 44 65 63 ... 6464 more bytes>
But the gm(filebuffer).toBuffer() is producing and empty thumbbuffer with Error: Stream yields empty buffer
What am I doing wrong here?
This appears to be a png issue, as jpg seems to work with both, .stream() and .toBuffer().
I'll settle for jpg until I can figure out what's wrong with png.
async function createThumbnail(newthumbname, mimetype, filebuffer) {
const file = bucket.file(newthumbname)
const thumbstream = file.createWriteStream({metadata:{contentType:mimetype}})
const gm = require('gm').subClass({imageMagick: true})
gm(filebuffer)
// .setFormat("jpg")
// .stream()
// .pipe(thumbstream)
.toBuffer('jpg', (err, thumbbuffer)=>{
thumbstream.end(thumbbuffer)
})
}

Could not parse base64 DER-encoded ASN.1 public key from iOS in Golang

i have a projects in Golang with RSA enryption, so now, i have a Base64 public key format which used for encrypt a message,
i used this code:
publicKeyBase64 = "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE="
publicKeyBinary, err := base64.StdEncoding.DecodeString(publicKeyBase64)
publicKeyInterface, err := x509.ParsePKIXPublicKey(publicKeyBinary)
if err != nil {
fmt.Println("Could not parse DER encoded public key (encryption key)")
return "","",err
}
publicKey, isRSAPublicKey := publicKeyInterface.(*rsa.PublicKey)
if !isRSAPublicKey {
fmt.Println("Public key parsed is not an RSA public key")
return "","",err
}
encryptedMessage, err := rsa.EncryptPKCS1v15(rand.Reader, publicKey, "message")
When i run this code, i got this error:
Could not parse DER encoded public key (encryption key)
asn1: structure error: tags don't match (16 vs {class:0 tag:2 length:129 isCompound:false}) {optional:false explicit:false application:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false} AlgorithmIdentifier #3
The error points to publicKeyInterface, it failed to parse from Base64 decoded format to public Key, What's the problem with my code ?
=======updated=====
my publicKeyBase64 is retrieved from my models with Binary Data type
When i store it in my mongoDB from my Rails API, i receive public_key params as Base64 format, but i decode it to binary and then i stored it with this code
def create
params = device_params
public_key = Base64.decode64 device_params[:public_key]
#device_params[:public_key] value is "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE="
params[:public_key] = BSON::Binary.new(public_key, :generic)
device = Device.find_or_create_by(id: device_params[:id])
render_success device.update_attributes(params), device
end
When i use rails code to convert my Base64 public key string using this code, it succeeded:
rsa_public_key = OpenSSL::PKey::RSA.new(Base64.decode64(public_key))
in my iOS app, i use https://github.com/DigitalLeaves/AsymmetricCrypto
to generate a public Key using this code:
AsymmetricCryptoManager.sharedInstance.createSecureKeyPair({ (success, error) -> Void in
if success {
print("RSA-1024 keypair successfully generated.")
let publicKey = AsymmetricCryptoManager.sharedInstance.getPublicKeyData()?.base64EncodedString()
let url = ENV.BASE_URL + "devices"
let headers = ["Authentication-Token": CurrentUser.getCurrentUser().token] as! HTTPHeaders
let params = ["device[user_id]": CurrentUser.getCurrentUser().id!, "device[id]": instanceID,"device[token]": fcmToken, "device[os]": "ios", "device[public_key]": publicKey!]
Alamofire.request(url, method: .post, parameters: params, encoding: URLEncoding.default, headers: headers)
} else { print("An error happened while generating a keypair: \(error)") }
})
We can dump the ASN.1 contents to see what they look like:
$ echo "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE=" | \
base64 -d | \
dumpasn1 -
0 137: SEQUENCE {
3 129: INTEGER
: 00 92 58 5E 00 5E 9B 5B 1C 2C A3 C4 8F 02 AB 5B
: CF 9C 8B 70 7F 60 D3 77 69 8D 83 27 79 5C E5 ED
: B0 35 CD 12 98 58 A4 0E 9A 30 D5 37 58 70 A9 76
: C1 DA D7 5F BB 0C 46 CC A3 4E 4D 79 20 40 8C 7B
: 3C 87 CD A2 46 43 D4 E2 9E 79 10 8B 12 7E 62 79
: 4D 74 B0 B4 E1 33 56 3A 0D 77 A6 5C 9A 84 85 C1
: 7E 8A D8 02 36 25 DB 05 48 03 C6 26 6B 66 C4 40
: 58 66 00 59 04 5F 50 3F 43 57 48 2B 2E 84 7D 0F
: B1
135 3: INTEGER 65537
: }
0 warnings, 0 errors.
A well-formatted ASN.1 public key should include the algorithm as well. We should have a line similar to:
5 9: OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
The AsymmetricCryptoManager.getPublicKeyData() returns a very barebones ASN.1 key, without any algorithm information. This makes Go very unhappy as it has no way of knowing what kind of key it is. See more about correctly exporting the key here.
If you can change the iOS code, you should instead use CryptoExportImportManager and use one of exportPublicKeyToPEM or exportPublicKeyToDER. These take the output of getPublicKeyData and generate output usable by other tools. You can find an example of how to use them in the CryptoExportImportManager example.
If you cannot change the key export code, you can instead parse it directly in Go. This assumes that you know for sure that it is a RSA public key:
func main() {
publicKeyBase64 := "MIGJAoGBAJJYXgBem1scLKPEjwKrW8+ci3B/YNN3aY2DJ3lc5e2wNc0SmFikDpow1TdYcKl2wdrXX7sMRsyjTk15IECMezyHzaJGQ9TinnkQixJ+YnlNdLC04TNWOg13plyahIXBforYAjYl2wVIA8Yma2bEQFhmAFkEX1A/Q1dIKy6EfQ+xAgMBAAE="
// Base64 decode.
publicKeyBinary, err := base64.StdEncoding.DecodeString(publicKeyBase64)
if err != nil {
panic(err)
}
// rsa.PublicKey is a big.Int (N: modulus) and an integer (E: exponent).
var pubKey rsa.PublicKey
if rest, err := asn1.Unmarshal(publicKeyBinary, &pubKey); err != nil {
panic(err)
} else if len(rest) != 0 {
panic("rest is not nil")
}
fmt.Printf("key: %+v\n", pubKey)
}
This prints out:
key:
{N:+102767083290202280873554060983826675083148443795791447833515664566475334389364583758312108980110921996262487865832851258326049062353432991986398760705560379825908169063986770245967781444794847106351934016144540466696422397564949226710181429429140226472206572796987719088983654589217713611861345869296293449649
E:65537}
You can now use your public key in package rsa functions.

String returns only numbers after separatedBy

I´m trying to separate a string like the following:
let path = "/Users/user/Downloads/history.csv"
do {
let contents = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue )
let rows = contents.components(separatedBy: "\n")
print("contents: \(contents)")
print("rows: \(rows)")
}
catch {
}
I have two files, which are looking almost identical.
From the first file the output is like this:
Output File1:
contents: 2017-07-31 16:29:53,0.10109999,9.74414271,0.98513273,0.15%,42302999779,-0.98513273,9.72952650
2017-07-31 16:29:53,0.10109999,0.25585729,0.02586716,0.25%,42302999779,-0.02586716,0.25521765
rows: ["2017-07-31 16:29:53,0.10109999,9.74414271,0.98513273,0.15%,42302999779,-0.98513273,9.72952650", "2017-07-31 16:29:53,0.10109999,0.25585729,0.02586716,0.25%,42302999779,-0.02586716,0.25521765", "", ""]
Output File2:
contents: 40.75013313,0.00064825,5/18/2017 7:17:01 PM
19.04004820,0.00059900,5/19/2017 9:17:03 PM
rows: ["4\00\0.\07\05\00\01\03\03\01\03\0,\00\0.\00\00\00\06\04\08\02\05\0,\05\0/\01\08\0/\02\00\01\07\0 \07\0:\01\07\0:\00\01\0 \0P\0M\0", "\0", "1\09\0.\00\04\00\00\04\08\02\00\0,\00\0.\00\00\00\05\09\09\00\00\0,\0\05\0/\01\09\0/\02\00\01\07\0 \09\0:\01\07\0:\00\03\0 \0P\0M\0", "\0", "\0", "\0"]
So both files are readable as String because the print(content) is working.
But as soon as the string gets separated, the second file is not readable anymore.
I tried different encodings, but nothing worked. Has anyone an idea, how to force the string to the second file, to remain a readable string?
Your file is apparently UTF-16 (little-endian) encoded:
$ hexdump fullorders4.csv
0000000 4f 00 72 00 64 00 65 00 72 00 55 00 75 00 69 00
0000010 64 00 2c 00 45 00 78 00 63 00 68 00 61 00 6e 00
0000020 67 00 65 00 2c 00 54 00 79 00 70 00 65 00 2c 00
0000030 51 00 75 00 61 00 6e 00 74 00 69 00 74 00 79 00
...
For ASCII characters, the first byte of the UTF-16 encoding is the
ASCII code, and the second byte is zero.
If the file is read as UTF-8 then the zeros are converted to an
ASCII NUL character, that is what you see as \0 in the output.
Therefore specifying the encoding as utf16LittleEndian works
in your case:
let contents = try NSString(contentsOfFile: path, encoding: String.Encoding.utf16LittleEndian.rawValue)
// or:
let contents = try String(contentsOfFile: path, encoding: .utf16LittleEndian)
There is also a method which tries to detect the used encoding
(compare iOS: What's the best way to detect a file's encoding). In Swift that would be
var enc: UInt = 0
let contents = try NSString(contentsOfFile: path, usedEncoding: &enc)
// or:
var enc = String.Encoding.ascii
let contents = try String(contentsOfFile: path, usedEncoding: &enc)
However, in your particular case, that would read the file as UTF-8
again because it is valid UTF-8. Prepending a byte order mark (BOM)
to the file (FF FE for UTF-16 little-endian) would solve that
problem reliably.

Constant TAO CORBA IOR

How to configure TAO corba server so that IOR string of this server generated from object_to_string is constant?
Each time the IOR string generated from object_to_string changes once server restarts. This is inconvenient since client has to update its cached server IOR string via reloading IOR file or namingservice accessing. As a result, it would be useful if server can generate a constant IOR string, no matter how many times it restarts.
My corba server is based on ACE+TAO and i do remember TAO supports constant IOR string: the IOR string each time it generates are same, and the solution is add some configurations for server. But i could not remember these configurations now.
=============================================
UPDATE:
In ACE_wrappers/TAO/tests/POA/Persistent_ID/server.cpp, i added a new function named testUniqe() which is similiar to creatPOA method. And the update file content is:
void testUniqu(CORBA::ORB_ptr orb_, PortableServer::POA_ptr poa_){
CORBA::PolicyList policies (2);
policies.length (2);
//IOR is the same even it is SYSTEM_ID
policies[0] = poa_->create_id_assignment_policy (PortableServer::USER_ID);
policies[1] = poa_->create_lifespan_policy (PortableServer::PERSISTENT);
PortableServer::POAManager_var poa_manager = poa_->the_POAManager ();
PortableServer::POA_ptr child_poa_ = poa_->create_POA ("childPOA", poa_manager.in (), policies);
// Destroy the policies
for (CORBA::ULong i = 0; i < policies.length (); ++i) {
policies[i]->destroy ();
}
test_i *servant = new test_i (orb_, child_poa_);
PortableServer::ObjectId_var oid = PortableServer::string_to_ObjectId("xushijie");
child_poa_->activate_object_with_id (oid, servant);
PortableServer::ObjectId_var id = poa_->activate_object (servant);
CORBA::Object_var object = poa_->id_to_reference (id.in ());
test_var test = test::_narrow (object.in ());
CORBA::String_var ior = orb_->object_to_string(test.in());
std::cout<<ior.in()<<std::endl;
poa_->the_POAManager()->activate();
orb_->run();
}
int
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{
try
{
CORBA::ORB_var orb =
CORBA::ORB_init (argc, argv);
int result = parse_args (argc, argv);
CORBA::Object_var obj =
orb->resolve_initial_references ("RootPOA");
PortableServer::POA_var root_poa =
PortableServer::POA::_narrow (obj.in ());
PortableServer::POAManager_var poa_manager =
root_poa->the_POAManager ();
testUniqu(orb.in(), root_poa.in());
orb->destroy ();
}
catch (const CORBA::Exception& ex)
{
ex._tao_print_exception ("Exception caught");
return -1;
}
return 0;
}
The problem is that the output server IORs are still different once restart. I also compared this code to the one in Page 412(Advance Corba Programming), but still fail..
///////////////////////////////////
UPDATE:
With "server -ORBListenEndpoints iiop://:1234 > /tmp/ior1", the generated two IORs are:
IOR:010000000d00000049444c3a746573743a312e300000000001000000000000007400000001010200150000007368696a69652d5468696e6b5061642d543431300000d2041b00000014010f0052535453f60054c6f80c000000000001000000010000000002000000000000000800000001000000004f41540100000018000000010000000100010001000000010001050901010000000000
IOR:010000000d00000049444c3a746573743a312e300000000001000000000000007400000001010200150000007368696a69652d5468696e6b5061642d543431300000d2041b00000014010f0052535468f60054da280a000000000001000000010000000002000000000000000800000001000000004f41540100000018000000010000000100010001000000010001050901010000000000
The result for tao_catior for ior1 and ior2:
ior1:
The Byte Order: Little Endian
The Type Id: "IDL:test:1.0"
Number of Profiles in IOR: 1
Profile number: 1
IIOP Version: 1.2
Host Name: **
Port Number: 1234
Object Key len: 27
Object Key as hex:
14 01 0f 00 52 53 54 53 f6 00 54 c6 f8 0c 00 00
00 00 00 01 00 00 00 01 00 00 00
The Object Key as string:
....RSTS..T................
The component <1> ID is 00 (TAG_ORB_TYPE)
ORB Type: 0x54414f00 (TAO)
The component <2> ID is 11 (TAG_CODE_SETS)
Component length: 24
Component byte order: Little Endian
Native CodeSet for char: Hex - 10001 Description - ISO8859_1
Number of CCS for char 1
Conversion Codesets for char are:
1) Hex - 5010001 Description - UTF-8
Native CodeSet for wchar: Hex - 10109 Description - UTF-16
Number of CCS for wchar 0
ecoding an IOR:
//ior2
The Byte Order: Little Endian
The Type Id: "IDL:test:1.0"
Number of Profiles in IOR: 1
Profile number: 1
IIOP Version: 1.2
Host Name: **
Port Number: 1234
Object Key len: 27
Object Key as hex:
14 01 0f 00 52 53 54 68 f6 00 54 da 28 0a 00 00
00 00 00 01 00 00 00 01 00 00 00
The Object Key as string:
....RSTh..T.(..............
The component <1> ID is 00 (TAG_ORB_TYPE)
ORB Type: 0x54414f00 (TAO)
The component <2> ID is 11 (TAG_CODE_SETS)
Component length: 24
Component byte order: Little Endian
Native CodeSet for char: Hex - 10001 Description - ISO8859_1
Number of CCS for char 1
Conversion Codesets for char are:
1) Hex - 5010001 Description - UTF-8
Native CodeSet for wchar: Hex - 10109 Description - UTF-16
Number of CCS for wchar 0
The diff result is:
< 14 01 0f 00 52 53 54 53 f6 00 54 c6 f8 0c 00 00
---
> 14 01 0f 00 52 53 54 68 f6 00 54 da 28 0a 00 00
19c19
< ....RSTS..T................
---
> ....RSTh..T.(..............
Similar diff result is:
< 14 01 0f 00 52 53 54 62 fd 00 54 2c 9a 0e 00 00
---
> 14 01 0f 00 52 53 54 02 fd 00 54 f9 a9 09 00 00
19c19
< ....RSTb..T,...............
---
> ....RST...T................
The difference is in ObjectKey.
============================================
update:
Instead of using above code, i find a better solution with helper TAO_ORB_Manager which is used NamingService and TAO/examples/Simple. TAO_ORB_Manager encapsulates API and generate persistent IORs, as example code in Simple.cpp:
if (this->orb_manager_.init_child_poa (argc, argv, "child_poa") == -1){
CORBA::String_var str =
this->orb_manager_.activate_under_child_poa (servant_name,
this->servant_.in ());
}
This is some description for TAO_ORB_Manager:
class TAO_UTILS_Export TAO_ORB_Manager
{
/**
* Creates a child poa under the root poa with PERSISTENT and
* USER_ID policies. Call this if you want a #a child_poa with the
* above policies, otherwise call init.
*
* #retval -1 Failure
* #retval 0 Success
*/
int init_child_poa (int &argc,
ACE_TCHAR *argv[],
const char *poa_name,
const char *orb_name = 0);
/**
* Precondition: init_child_poa has been called. Activate <servant>
* using the POA <activate_object_with_id> created from the string
* <object_name>. Users should call this to activate objects under
* the child_poa.
*
* #param object_name String name which will be used to create
* an Object ID for the servant.
* #param servant The servant to activate under the child POA.
*
* #return 0 on failure, a string representation of the object ID if
* successful. Caller of this method is responsible for
* memory deallocation of the string.
*/
char *activate_under_child_poa (const char *object_name,
PortableServer::Servant servant);
...................
}
After build, I can get what i want with -ORBListenEndpoints iiop://localhost:2809 option. Thanks #Johnny Willemsen help
You have to create the POA with a persistent lifespan policy, see ACE_wrappers/TAO/tests/POA/Persistent_ID as part of the TAO distribution.

SNMP trap via Indy plus russian letters

I send snmp traps from borland c++ application using indy components, (thanks Remy Lebeau for working example Implementing SNMP SendTrap using Indy components) But I have problem with russian letters.
void __fastcall TMainForm::QuickSendTrap()
{
String myEnterprise = _D("1.5.5.5.5.5.5.5");
String eventType = myEnterprise + _D(".1");
String eventDistance = myEnterprise + _D(".2");
String eventTitle1 = myEnterprise + _D(".3");
String eventTitle2 = myEnterprise + _D(".4");
String eventTitle3 = myEnterprise + _D(".5");
TStringList *names = new TStringList;
names->Add(eventType);
names->Add(eventDistance);
names->Add(eventTitle1);
names->Add(eventTitle2);
names->Add(eventTitle3);
TStringList *values = new TStringList;
values->AddObject(_D("ftCritical"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("2.357"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("АБВГД"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("абвгд"), (TObject*)ASN1_OCTSTR);
values->AddObject(_D("ОПРСТ"), (TObject*)ASN1_OCTSTR);
TIdSNMP *idSnmp = new TIdSNMP(NULL);
idSnmp->QuickSendTrap(edHost->Text, myEnterprise, _D("public"), 162, 6, 1, names, values);
delete idSnmp;
delete names;
delete values;
}
Instead of russian symbols Wireshark see "?"
0000 30 81 8b 02 01 00 04 06 70 75 62 6c 69 63 a4 7e 0.......public.~
0010 06 07 2d 05 05 05 05 05 05 40 04 c0 a8 64 56 02 ..-......#...dV.
0020 01 06 02 01 01 43 01 00 30 64 30 16 06 08 2d 05 .....C..0d0...-.
0030 05 05 05 05 05 01 04 0a 66 74 43 72 69 74 69 63 ........ftCritic
0040 61 6c 30 11 06 08 2d 05 05 05 05 05 05 02 04 05 al0...-.........
0050 32 2e 33 35 37 30 11 06 08 2d 05 05 05 05 05 05 2.3570...-......
0060 03 04 05 3f 3f 3f 3f 3f 30 11 06 08 2d 05 05 05 ...?????0...-...
0070 05 05 05 04 04 05 3f 3f 3f 3f 3f 30 11 06 08 2d ......?????0...-
0080 05 05 05 05 05 05 05 04 05 3f 3f 3f 3f 3f .........?????
The question is how to encode russian string for snmp properly?
Unfortunately, TIdSNMP does not support non-ASCII data at this time. This is because:
Indy's ASN.1 encode/decode functions have not been made encoding-aware yet so that strings can be converted to/from byte arrays using charsets.
TSNMPInfo encodes PDU data to a String first and then encodes that String to bytes using Indy's 8bit encoding when sending. Thus, any Unicode codepoints greater than #255 will get converted to ?. The Russian characters you are trying to send all have Unicode codepoint values greater than #255. There is no option to specify a different encoding, even though ASN.1 octet strings can technically carry character data encoded in any 8bit charset as long as both parties agree to the charset used.
In order to send cyrillic symbols via Indy's Snmp component I implemented functions which "hide" message in different encoding inside UnicodeString that used by TIdSnmp.
UnicodeString TMainForm::Windows1251ForSnmp(AnsiString str)
{
UnicodeString ustr = "";
for (int i = 0; i < str.Length(); i++)
{
unsigned char cc = *(str.c_str()+i);
wchar_t buff = 0;
memcpy((char*)&buff, &cc, 1);
ustr = ustr + buff;
}
return ustr;
}
UnicodeString TMainForm::Utf8ForSnmp(UTF8String str)
{
UnicodeString ustr = "";
for (int i = 0; i < str.Length(); i++)
{
unsigned char cc = *(str.c_str()+i);
wchar_t buff = 0;
memcpy((char*)&buff, &cc, 1);
ustr = ustr + buff;
}
return ustr;
}
UnicodeString TMainForm::Utf16ForSnmp(UnicodeString str)
{
UnicodeString ustr = "";
for (int i = 0; i < str.Length(); i++)
{
unsigned int cc = *(str.c_str()+i);
byte a = cc / 256;
byte b = cc % 256;
ustr = ustr + char(a);
ustr = ustr + char(b);
}
return ustr;
}
After message conversion by one of these functions I gave result to Indy component TIdSnmp as usually and it will be send without problem.
UnicodeString ustr = Windows1251ForSnmp("Русский");
UTF8String param = _D("Русский");
UnicodeString ustr2 = Utf8ForSnmp(param);
UnicodeString ustr3 = Utf16ForSnmp("Русский");
values->AddObject(ustr, (TObject*)ASN1_OCTSTR);
values->AddObject(ustr2, (TObject*)ASN1_OCTSTR);
values->AddObject(ustr3, (TObject*)ASN1_OCTSTR);
So, on the "other side" I recieved russian messages in Windows1251, Utf8 and Utf16 encoding.

Resources