001/**
002 *
003 * Copyright 2017 Paul Schaub
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smackx.omemo.provider;
018
019import static org.jivesoftware.smackx.omemo.element.OmemoElement.ENCRYPTED;
020import static org.jivesoftware.smackx.omemo.element.OmemoElement.HEADER;
021import static org.jivesoftware.smackx.omemo.element.OmemoElement.IV;
022import static org.jivesoftware.smackx.omemo.element.OmemoElement.KEY;
023import static org.jivesoftware.smackx.omemo.element.OmemoElement.PAYLOAD;
024import static org.jivesoftware.smackx.omemo.element.OmemoElement.PREKEY;
025import static org.jivesoftware.smackx.omemo.element.OmemoElement.RID;
026import static org.jivesoftware.smackx.omemo.element.OmemoElement.SID;
027import static org.xmlpull.v1.XmlPullParser.END_TAG;
028import static org.xmlpull.v1.XmlPullParser.START_TAG;
029
030import java.util.ArrayList;
031
032import org.jivesoftware.smack.provider.ExtensionElementProvider;
033import org.jivesoftware.smack.util.stringencoder.Base64;
034
035import org.jivesoftware.smackx.omemo.element.OmemoVAxolotlElement;
036
037import org.xmlpull.v1.XmlPullParser;
038
039/**
040 * Smack ExtensionProvider that parses incoming OMEMO Message element into OmemoMessageElement objects.
041 *
042 * @author Paul Schaub
043 */
044public class OmemoVAxolotlProvider extends ExtensionElementProvider<OmemoVAxolotlElement> {
045
046    @Override
047    public OmemoVAxolotlElement parse(XmlPullParser parser, int initialDepth) throws Exception {
048        boolean inEncrypted = true;
049        int sid = -1;
050        ArrayList<OmemoVAxolotlElement.OmemoHeader.Key> keys = new ArrayList<>();
051        byte[] iv = null;
052        byte[] payload = null;
053
054        while (inEncrypted) {
055            int tag = parser.next();
056            String name = parser.getName();
057            switch (tag) {
058                case START_TAG:
059                    switch (name) {
060                        case HEADER:
061                            for (int i = 0; i < parser.getAttributeCount(); i++) {
062                                if (parser.getAttributeName(i).equals(SID)) {
063                                    sid = Integer.parseInt(parser.getAttributeValue(i));
064                                }
065                            }
066                            break;
067                        case KEY:
068                            boolean prekey = false;
069                            int rid = -1;
070                            for (int i = 0; i < parser.getAttributeCount(); i++) {
071                                if (parser.getAttributeName(i).equals(PREKEY)) {
072                                    prekey = Boolean.parseBoolean(parser.getAttributeValue(i));
073                                } else if (parser.getAttributeName(i).equals(RID)) {
074                                    rid = Integer.parseInt(parser.getAttributeValue(i));
075                                }
076                            }
077                            keys.add(new OmemoVAxolotlElement.OmemoHeader.Key(Base64.decode(parser.nextText()), rid, prekey));
078                            break;
079                        case IV:
080                            iv = Base64.decode(parser.nextText());
081                            break;
082                        case PAYLOAD:
083                            payload = Base64.decode(parser.nextText());
084                            break;
085                    }
086                    break;
087                case END_TAG:
088                    if (name.equals(ENCRYPTED)) {
089                        inEncrypted = false;
090                    }
091                    break;
092            }
093        }
094        OmemoVAxolotlElement.OmemoHeader header = new OmemoVAxolotlElement.OmemoHeader(sid, keys, iv);
095        return new OmemoVAxolotlElement(header, payload);
096    }
097}