public String toString(boolean prefix, boolean pureAscii) { if (keyType == null) { // Not activated or something... if (logMINOR) Logger.minor(this, "Not activated?? in toString(" + prefix + "," + pureAscii + ")"); return null; } StringBuilder b; if (prefix) b = new StringBuilder("freenet:"); else b = new StringBuilder(); b.append(keyType).append('@'); if (!"KSK".equals(keyType)) { if (routingKey != null) b.append(Base64.encode(routingKey)); if (cryptoKey != null) b.append(',').append(Base64.encode(cryptoKey)); if (extra != null) b.append(',').append(Base64.encode(extra)); if (docName != null) b.append('/'); } if (docName != null) b.append(URLEncoder.encode(docName, "/", pureAscii)); if (keyType.equals("USK")) { b.append('/'); b.append(suggestedEdition); } if (metaStr != null) for (int i = 0; i < metaStr.length; i++) { b.append('/').append(URLEncoder.encode(metaStr[i], "/", pureAscii)); } return b.toString(); }
public String getPreferredFilename() { if (logMINOR) Logger.minor(this, "Getting preferred filename for " + this); ArrayList<String> names = new ArrayList<String>(); if (keyType != null && (keyType.equals("KSK") || keyType.equals("SSK") || keyType.equals("USK"))) { if (logMINOR) Logger.minor(this, "Adding docName: " + docName); names.add(docName); if (keyType.equals("USK")) names.add(Long.toString(suggestedEdition)); } if (metaStr != null) for (int i = 0; i < metaStr.length; i++) { if (logMINOR) Logger.minor(this, "Adding metaString " + i + ": " + metaStr[i]); names.add(metaStr[i]); } StringBuilder out = new StringBuilder(); for (int i = 0; i < names.size(); i++) { String s = names.get(i); if (logMINOR) Logger.minor(this, "name " + i + " = " + s); s = FileUtil.sanitize(s); if (logMINOR) Logger.minor(this, "Sanitized name " + i + " = " + s); if (s.length() > 0) { if (out.length() > 0) out.append('-'); out.append(s); } } if (logMINOR) Logger.minor(this, "out = " + out.toString()); if (out.length() == 0) { if (routingKey != null) { if (logMINOR) Logger.minor(this, "Returning base64 encoded routing key"); return Base64.encode(routingKey); } return "unknown"; } return out.toString(); }
public String getDomain() { try { return Base32.encode(Base64.decode(identity)).toLowerCase(Locale.ROOT) + ".freemail"; } catch (IllegalBase64Exception e) { // This would mean that WoT has changed the encoding of the identity string throw new AssertionError("Got IllegalBase64Exception when decoding " + identity); } }
public void exportIntroductionPuzzle(IntroductionPuzzle puzzle, OutputStream os) throws TransformerException, ParserConfigurationException { Document xmlDoc; synchronized ( mDocumentBuilder) { // TODO: Figure out whether the DocumentBuilder is maybe synchronized // anyway xmlDoc = mDOM.createDocument(null, WebOfTrust.WOT_NAME, null); } // 1.0 does not support all Unicode characters which the String class supports. To prevent us // from having to filter all Strings, we use 1.1 xmlDoc.setXmlVersion("1.1"); Element rootElement = xmlDoc.getDocumentElement(); // We include the WoT version to have an easy way of handling bogus XML which might be created // by bugged versions. rootElement.setAttribute("Version", Long.toString(Version.getRealVersion())); Element puzzleElement = xmlDoc.createElement("IntroductionPuzzle"); puzzleElement.setAttribute( "Version", Integer.toString(INTRODUCTION_XML_FORMAT_VERSION)); /* Version of the XML format */ // This lock is actually not necessary because all values which are taken from the puzzle are // final. We leave it here just to make sure that it does // not get lost if it becomes necessary someday. synchronized (puzzle) { puzzleElement.setAttribute("ID", puzzle.getID()); puzzleElement.setAttribute("Type", puzzle.getType().toString()); puzzleElement.setAttribute("MimeType", puzzle.getMimeType()); synchronized (mDateFormat) { puzzleElement.setAttribute("ValidUntil", mDateFormat.format(puzzle.getValidUntilDate())); } Element dataElement = xmlDoc.createElement("Data"); dataElement.setAttribute("Value", Base64.encodeStandard(puzzle.getData())); puzzleElement.appendChild(dataElement); } rootElement.appendChild(puzzleElement); DOMSource domSource = new DOMSource(xmlDoc); StreamResult resultStream = new StreamResult(os); synchronized (mSerializer) { mSerializer.transform(domSource, resultStream); } }
public IntroductionPuzzle getIntroductionPuzzle(String id) throws Exception { SimpleFieldSet params = new SimpleFieldSet(true); params.putOverwrite("Message", "GetIntroductionPuzzle"); params.putOverwrite("Puzzle", id); try { SimpleFieldSet result = sendFCPMessageBlocking(params, null, "IntroductionPuzzle").params; try { return new IntroductionPuzzle( id, result.get("MimeType"), Base64.decodeStandard(result.get("Data"))); } catch (RuntimeException e) { Logger.error(this, "Parsing puzzle failed", e); } catch (IllegalBase64Exception e) { Logger.error(this, "Parsing puzzle failed", e); } return null; } catch (PluginNotFoundException e) { Logger.error(this, "Getting puzzles failed", e); return null; } }
FreemailAccount(String identity, File _accdir, PropsFile _accprops, Freemail freemail) { if (!FreenetURI.checkSSKHash(identity)) { throw new IllegalArgumentException("Expected valid identity string, but got " + identity); } try { Base64.decode(identity); } catch (IllegalBase64Exception e) { throw new IllegalArgumentException("Couldn't decode identity string: " + identity, e); } this.identity = identity; accdir = _accdir; accprops = _accprops; mb = new MessageBank(this); File channelDir = new File(accdir, "channel"); messageHandler = new MessageHandler( new File(accdir, "outbox"), freemail, channelDir, this, new HighLevelFCPClientFactory()); }
// TODO: Replace with IdentityID.constructFromURI public static String getIDFromURI(FreenetURI uri) { /* WARNING: This is a copy of the code of plugins.WoT.Identity. Freetalk is not allowed to have its own custom IDs, you cannot change * this code here. */ return Base64.encode(uri.getRoutingKey()); }
public FreenetURI(String URI) throws MalformedURLException { // this.uniqueHashCode = super.hashCode(); if (URI == null) throw new MalformedURLException("No URI specified"); URI = URI.trim(); if (URI.indexOf('@') < 0 || URI.indexOf('/') < 0) // Encoded URL? try { URI = URLDecoder.decode(URI, false); } catch (URLEncodedFormatException e) { throw new MalformedURLException( "Invalid URI: no @ or /, or @ or / is escaped but there are invalid escapes"); } URI = URI_PREFIX.matcher(URI).replaceFirst(""); // decode keyType int atchar = URI.indexOf('@'); if (atchar == -1) throw new MalformedURLException("There is no @ in that URI! (" + URI + ')'); String _keyType = URI.substring(0, atchar).toUpperCase(); URI = URI.substring(atchar + 1); boolean validKeyType = false; for (int i = 0; i < VALID_KEY_TYPES.length; i++) { if (_keyType.equals(VALID_KEY_TYPES[i])) { validKeyType = true; _keyType = VALID_KEY_TYPES[i]; break; } } keyType = _keyType; if (!validKeyType) throw new MalformedURLException("Invalid key type: " + keyType); boolean isSSK = "SSK".equals(keyType); boolean isUSK = "USK".equals(keyType); boolean isKSK = "KSK".equals(keyType); // decode metaString ArrayList<String> sv = null; int slash2; sv = new ArrayList<String>(); if (isKSK) URI = "/" + URI; // ensure that KSK docNames are decoded while ((slash2 = URI.lastIndexOf('/')) != -1) { String s; try { s = URLDecoder.decode(URI.substring(slash2 + 1 /* "/".length() */), true); } catch (URLEncodedFormatException e) { MalformedURLException ue = new MalformedURLException(e.toString()); ue.initCause(e); throw ue; } if (s != null) sv.add(s); URI = URI.substring(0, slash2); } // sv is *backwards* // this makes for more efficient handling if (isSSK || isUSK || isKSK) { if (sv.isEmpty()) throw new MalformedURLException("No docname for " + keyType); docName = sv.remove(sv.size() - 1); if (isUSK) { if (sv.isEmpty()) throw new MalformedURLException("No suggested edition number for USK"); try { suggestedEdition = Long.parseLong(sv.remove(sv.size() - 1)); } catch (NumberFormatException e) { MalformedURLException e1 = new MalformedURLException("Invalid suggested edition: " + e); e1.initCause(e); throw e1; } } else suggestedEdition = -1; } else { // docName not necessary, nor is it supported, for CHKs. docName = null; suggestedEdition = -1; } if (!sv.isEmpty()) { metaStr = new String[sv.size()]; for (int i = 0; i < metaStr.length; i++) { metaStr[i] = sv.get(metaStr.length - 1 - i).intern(); if (metaStr[i] == null) throw new NullPointerException(); } } else metaStr = null; if (isKSK) { routingKey = extra = cryptoKey = null; return; } // strip 'file extensions' from CHKs // added by aum ([email protected]) if ("CHK".equals(keyType)) URI = URI.split("[.]")[0]; // URI now contains: routingKey[,cryptoKey][,metaInfo] StringTokenizer st = new StringTokenizer(URI, ","); try { if (st.hasMoreTokens()) routingKey = Base64.decode(st.nextToken()); else { routingKey = cryptoKey = extra = null; return; } if (!st.hasMoreTokens()) { cryptoKey = extra = null; return; } // Can be cryptokey or name-value pair. String t = st.nextToken(); cryptoKey = Base64.decode(t); if (!st.hasMoreTokens()) { extra = null; return; } extra = Base64.decode(st.nextToken()); } catch (IllegalBase64Exception e) { throw new MalformedURLException("Invalid Base64 quantity: " + e); } if (logDEBUG) Logger.minor( this, "Created from parse: " + toString() + " from " + URI, new Exception("debug")); }
/** * @param xmlInputStream An InputStream which must not return more than {@link * MAX_INTRODUCTIONPUZZLE_BYTE_SIZE} bytes. */ public IntroductionPuzzle importIntroductionPuzzle( FreenetURI puzzleURI, InputStream xmlInputStream) throws SAXException, IOException, InvalidParameterException, UnknownIdentityException, IllegalBase64Exception, ParseException { xmlInputStream = new OneBytePerReadInputStream( xmlInputStream); // Workaround for Java bug, see the stream class for explanation // May not be accurate by definition of available(). So the JavaDoc requires the callers to obey // the size limit, this is a double-check. if (xmlInputStream.available() > MAX_INTRODUCTIONPUZZLE_BYTE_SIZE) throw new IllegalArgumentException( "XML contains too many bytes: " + xmlInputStream.available()); String puzzleID; IntroductionPuzzle.PuzzleType puzzleType; String puzzleMimeType; Date puzzleValidUntilDate; byte[] puzzleData; Document xmlDoc; synchronized ( mDocumentBuilder) { // TODO: Figure out whether the DocumentBuilder is maybe synchronized // anyway xmlDoc = mDocumentBuilder.parse(xmlInputStream); } Element puzzleElement = (Element) xmlDoc.getElementsByTagName("IntroductionPuzzle").item(0); if (Integer.parseInt(puzzleElement.getAttribute("Version")) > INTRODUCTION_XML_FORMAT_VERSION) throw new InvalidParameterException( "Version " + puzzleElement.getAttribute("Version") + " > " + INTRODUCTION_XML_FORMAT_VERSION); puzzleID = puzzleElement.getAttribute("ID"); puzzleType = IntroductionPuzzle.PuzzleType.valueOf(puzzleElement.getAttribute("Type")); puzzleMimeType = puzzleElement.getAttribute("MimeType"); synchronized (mDateFormat) { puzzleValidUntilDate = mDateFormat.parse(puzzleElement.getAttribute("ValidUntil")); } Element dataElement = (Element) puzzleElement.getElementsByTagName("Data").item(0); puzzleData = Base64.decodeStandard(dataElement.getAttribute("Value")); IntroductionPuzzle puzzle; synchronized (mWoT) { Identity puzzleInserter = mWoT.getIdentityByURI(puzzleURI); puzzle = new IntroductionPuzzle( mWoT, puzzleInserter, puzzleID, puzzleType, puzzleMimeType, puzzleData, IntroductionPuzzle.getDateFromRequestURI(puzzleURI), puzzleValidUntilDate, IntroductionPuzzle.getIndexFromRequestURI(puzzleURI)); mWoT.getIntroductionPuzzleStore().storeAndCommit(puzzle); } return puzzle; }
@Override public String toString() { return super.toString() + '@' + Base64.encode(routingKey) + ':' + Integer.toHexString(hash); }