View Javadoc
1   /*
2    * Copyright 2024 Michael Osipov
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package net.sf.michaelo.tomcat.pac;
17  
18  import java.math.BigInteger;
19  import java.nio.Buffer;
20  import java.nio.ByteBuffer;
21  import java.nio.ByteOrder;
22  
23  /**
24   * A thin wrapper around {@link ByteBuffer} to comply with the encoding rules defined by the
25   * <a href=
26   * "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/6655b92f-ab06-490b-845d-037e6987275f">{@code PACTYPE}</a>
27   * structure from MS-PAC.
28   */
29  public class PacDataBuffer {
30  
31  	private static final BigInteger TWO_COMPL_REF = BigInteger.ONE.shiftLeft(64);
32  
33  	private final ByteBuffer buf;
34  
35  	/**
36  	 * Constructs a PAC data buffer from a byte array.
37  	 *
38  	 * @param pacDataBytes
39  	 *            PAC data encoded as bytes
40  	 */
41  	public PacDataBuffer(byte[] pacDataBytes) {
42  		buf = ByteBuffer.wrap(pacDataBytes);
43  		buf.order(ByteOrder.LITTLE_ENDIAN);
44  	}
45  
46  	public int position() {
47  		return ((Buffer) buf).position();
48  	}
49  
50  	public PacDataBuffer position(int newPosition) {
51  		((Buffer) buf).position(newPosition);
52  		return this;
53  	}
54  
55  	public PacDataBuffer skip(int bytes) {
56  		((Buffer) buf).position(buf.position() + bytes);
57  		return this;
58  	}
59  
60  	protected PacDataBuffer align(int bytes) {
61  		int shift = ((Buffer) buf).position() & bytes - 1;
62  		if (bytes != 0 && shift != 0)
63  			skip(bytes - shift);
64  		return this;
65  	}
66  
67  	public PacDataBuffer get(byte[] dst) {
68  		buf.get(dst);
69  		return this;
70  	}
71  
72  	public int getInt() {
73  		align(4);
74  		return buf.getInt();
75  	}
76  
77  	public int getUnsignedShort() {
78  		align(2);
79  		return buf.getShort() & 0xffff;
80  	}
81  
82  	public long getUnsignedInt() {
83  		align(4);
84  		return buf.getInt() & 0xffffffffL;
85  	}
86  
87  	public BigInteger getUnsignedLong() {
88  		align(8);
89  		long temp = buf.getLong();
90  		BigInteger value = BigInteger.valueOf(temp);
91  		if (value.compareTo(BigInteger.ZERO) < 0)
92  			value = value.add(TWO_COMPL_REF);
93  		return value;
94  	}
95  
96  }