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