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.ATTR_PAYLOAD;
020
021import java.io.IOException;
022import java.util.ArrayList;
023
024import org.jivesoftware.smack.packet.XmlEnvironment;
025import org.jivesoftware.smack.provider.ExtensionElementProvider;
026import org.jivesoftware.smack.util.stringencoder.Base64;
027import org.jivesoftware.smack.xml.XmlPullParser;
028import org.jivesoftware.smack.xml.XmlPullParserException;
029
030import org.jivesoftware.smackx.omemo.element.OmemoElement_VAxolotl;
031import org.jivesoftware.smackx.omemo.element.OmemoHeaderElement;
032import org.jivesoftware.smackx.omemo.element.OmemoHeaderElement_VAxolotl;
033import org.jivesoftware.smackx.omemo.element.OmemoKeyElement;
034
035import org.jxmpp.JxmppContext;
036
037/**
038 * Smack ExtensionProvider that parses incoming OMEMO Message element into OmemoMessageElement objects.
039 *
040 * @author Paul Schaub
041 */
042public class OmemoVAxolotlProvider extends ExtensionElementProvider<OmemoElement_VAxolotl> {
043
044    @Override
045    public OmemoElement_VAxolotl parse(XmlPullParser parser, int initialDepth, XmlEnvironment xmlEnvironment, JxmppContext jxmppContext) throws XmlPullParserException, IOException {
046        int sid = -1;
047        ArrayList<OmemoKeyElement> keys = new ArrayList<>();
048        byte[] iv = null;
049        byte[] payload = null;
050
051        outerloop: while (true) {
052            XmlPullParser.Event tag = parser.next();
053            switch (tag) {
054                case START_ELEMENT:
055                    String name = parser.getName();
056                    switch (name) {
057                        case OmemoHeaderElement.ELEMENT:
058                            for (int i = 0; i < parser.getAttributeCount(); i++) {
059                                if (parser.getAttributeName(i).equals(OmemoHeaderElement.ATTR_SID)) {
060                                    sid = Integer.parseInt(parser.getAttributeValue(i));
061                                }
062                            }
063                            break;
064                        case OmemoKeyElement.ELEMENT:
065                            boolean prekey = false;
066                            int rid = -1;
067                            for (int i = 0; i < parser.getAttributeCount(); i++) {
068                                if (parser.getAttributeName(i).equals(OmemoKeyElement.ATTR_PREKEY)) {
069                                    prekey = Boolean.parseBoolean(parser.getAttributeValue(i));
070                                } else if (parser.getAttributeName(i).equals(OmemoKeyElement.ATTR_RID)) {
071                                    rid = Integer.parseInt(parser.getAttributeValue(i));
072                                }
073                            }
074                            keys.add(new OmemoKeyElement(Base64.decode(parser.nextText()), rid, prekey));
075                            break;
076                        case OmemoHeaderElement.ATTR_IV:
077                            iv = Base64.decode(parser.nextText());
078                            break;
079                        case ATTR_PAYLOAD:
080                            payload = Base64.decode(parser.nextText());
081                            break;
082                    }
083                    break;
084                case END_ELEMENT:
085                    if (parser.getDepth() == initialDepth) {
086                        break outerloop;
087                    }
088                    break;
089                default:
090                    // Catch all for incomplete switch (MissingCasesInEnumSwitch) statement.
091                    break;
092            }
093        }
094        OmemoHeaderElement_VAxolotl header = new OmemoHeaderElement_VAxolotl(sid, keys, iv);
095        return new OmemoElement_VAxolotl(header, payload);
096    }
097}