/* * Copyright 2009-2012 Michael Dalton * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package java.lang; import java.util.BitSet; import jtaint.SafeTaint; import jtaint.Taint; public final class SafeStringBuffer implements SafeCharSequence { private OrigStringBuffer buffer; private SafeTaint taint; public SafeStringBuffer() { buffer = new OrigStringBuffer(); taint = new SafeTaint(); } public SafeStringBuffer(int capacity) { buffer = new OrigStringBuffer(capacity); taint = new SafeTaint(); } public SafeStringBuffer(SafeString str) { buffer = new OrigStringBuffer(str.origString()); taint = str.taint(); } //[ifJava5+] public SafeStringBuffer(SafeCharSequence seq) { this(seq.toSafeString()); } //[fiJava5+] public synchronized int length() { return buffer.length(); } public synchronized int capacity() { return buffer.capacity(); } public synchronized void ensureCapacity(int minimumCapacity) { buffer.ensureCapacity(minimumCapacity); } //[ifJava5+] public synchronized void trimToSize() { buffer.trimToSize(); } //[fiJava5+] public synchronized void setLength(int newLength) { buffer.setLength(newLength); taint.setLength(newLength); } public synchronized char charAt(int index) { return buffer.charAt(index); } //[ifJava5+] public synchronized int codePointAt(int index) { return buffer.codePointAt(index); } public synchronized int codePointBefore(int index) { return buffer.codePointBefore(index); } public synchronized int codePointCount(int beginIndex, int endIndex) { return buffer.codePointCount(beginIndex, endIndex); } public synchronized int offsetByCodePoints(int index, int codePointOffset) { return buffer.offsetByCodePoints(index, codePointOffset); } //[fiJava5+] public synchronized void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) { buffer.getChars(srcBegin, srcEnd, dst, dstBegin); } public synchronized void setCharAt(int index, char ch) { buffer.setCharAt(index, ch); taint.clear(index); } public synchronized SafeStringBuffer append(Object obj) { return append(SafeString.valueOf(obj)); } public synchronized SafeStringBuffer append(SafeString str) { buffer.append(str.origString()); taint.append(str.taint()); return this; } public synchronized SafeStringBuffer append(SafeStringBuffer sb) { return append(sb.toSafeString()); } //[ifJava5+] public SafeStringBuffer append(SafeCharSequence s) { return append(s.toSafeString()); } public synchronized SafeStringBuffer append(SafeCharSequence s, int start, int end) { return append(s.toSafeString().substring(start, end)); } //[fiJava5+] public synchronized SafeStringBuffer append(char str[]) { return append(new SafeString(str)); } public synchronized SafeStringBuffer append(char str[], int offset, int len){ return append(new SafeString(str,offset,len)); } public synchronized SafeStringBuffer append(boolean b) { return append(SafeString.valueOf(b)); } public synchronized SafeStringBuffer append(char c) { return append(SafeString.valueOf(c)); } public synchronized SafeStringBuffer append(int i) { return append(SafeString.valueOf(i)); } //[ifJava5+] public synchronized SafeStringBuffer appendCodePoint(int codePoint) { buffer.appendCodePoint(codePoint); taint.setLength(buffer.length()); return this; } //[fiJava5+] public synchronized SafeStringBuffer append(long lng) { return append(SafeString.valueOf(lng)); } public synchronized SafeStringBuffer append(float f) { return append(SafeString.valueOf(f)); } public synchronized SafeStringBuffer append(double d) { return append(SafeString.valueOf(d)); } public synchronized SafeStringBuffer delete(int start, int end) { buffer.delete(start, end); taint.delete(start, end); return this; } public synchronized SafeStringBuffer deleteCharAt(int index) { if (index == buffer.length()) throw new IndexOutOfBoundsException("invalid index"); buffer.delete(index, index+1); taint.delete(index, index+1); return this; } public synchronized SafeStringBuffer replace(int start, int end, SafeString str) { buffer.replace(start, end, str.origString()); taint.delete(start, end); taint.insert(start, str.taint()); return this; } public synchronized SafeString substring(int start) { return substring(start, buffer.length()); } public synchronized CharSequence subSequence(int start, int end) { return substring(start, end); } public synchronized SafeString substring(int start, int end) { return toSafeString().substring(start, end); } public synchronized SafeStringBuffer insert(int index, char str[], int offset, int len) { return insert(index, new SafeString(str, offset, len)); } public synchronized SafeStringBuffer insert(int offset, Object obj) { return insert(offset, SafeString.valueOf(obj)); } public synchronized SafeStringBuffer insert(int offset, SafeString str) { buffer.insert(offset, str.origString()); taint.insert(offset, str.taint()); return this; } public synchronized SafeStringBuffer insert(int offset, char str[]) { return insert(offset, new SafeString(str)); } //[ifJava5+] public SafeStringBuffer insert(int dstOffset, SafeCharSequence s) { return insert(dstOffset, s.toSafeString()); } public synchronized SafeStringBuffer insert(int dstOffset, SafeCharSequence s, int start, int end) { return insert(dstOffset, s.toSafeString().substring(start, end)); } //[fiJava5+] public SafeStringBuffer insert(int offset, boolean b) { return insert(offset, SafeString.valueOf(b)); } public synchronized SafeStringBuffer insert(int offset, char c) { return insert(offset, SafeString.valueOf(c)); } public SafeStringBuffer insert(int offset, int i) { return insert(offset, SafeString.valueOf(i)); } public SafeStringBuffer insert(int offset, long l) { return insert(offset, SafeString.valueOf(l)); } public SafeStringBuffer insert(int offset, float f) { return insert(offset, SafeString.valueOf(f)); } public SafeStringBuffer insert(int offset, double d) { return insert(offset, SafeString.valueOf(d)); } public int indexOf(SafeString str) { return buffer.indexOf(str.origString()); } public synchronized int indexOf(SafeString str, int fromIndex) { return buffer.indexOf(str.origString(), fromIndex); } public int lastIndexOf(SafeString str) { return buffer.lastIndexOf(str.origString()); } public synchronized int lastIndexOf(SafeString str, int fromIndex) { return buffer.lastIndexOf(str.origString(), fromIndex); } public synchronized SafeStringBuffer reverse() { buffer.reverse(); taint.reverse(); return this; } public synchronized String toString() { String s = buffer.toString(); if (!taint.isTainted()) return s; else return new String(s, new Taint(taint.asBitSet(), s.length())); } public synchronized SafeString toSafeString() { return new SafeString(buffer.toOrigString(), (SafeTaint) taint.clone()); } public synchronized boolean verify(StringBuffer sb) throws IllegalArgumentException { Taint t = sb.toString().@internal@taint(); if (!buffer.toString().equals(sb.toString()) || !taint.verify(t)) return false; return true; } public synchronized SafeTaint taint() { return (SafeTaint) taint.clone(); } }