6 Commits

Author SHA1 Message Date
b472f63f17 Fix mistake in BUILD.txt 2020-10-15 01:01:30 +00:00
ad42cbe99b Add detailed instructions to build the plugin in BUILD.txt, known to build with from both the mtn and git mirrors 2020-10-14 22:57:18 +00:00
zzz
0c33a94f14 drop JSON license, no longer bundled 2020-08-23 14:31:41 +00:00
zzz
5b04a9cf40 0.6
Disable pack200
Update makeplugin.sh script
2020-06-08 12:50:11 +00:00
zzz
401271e911 0.5
Remove bundled libjson-simple which conflicts with i2p.jar
Switch to use libjson-simple 2.x API
Requires I2P 0.9.47
2020-05-31 13:46:34 +00:00
zzz
4025f49581 Fixes for Sonarr, v0.4 2017-03-26 16:57:08 +00:00
18 changed files with 158 additions and 1402 deletions

65
BUILD.txt Normal file
View File

@ -0,0 +1,65 @@
Setting up a build environment for I2PSnark-RPC
===============================================
These build instructions seem to work with both git and mtn.
1. You can build I2PSnark-RPC using either the packages that come with
an I2P installation or with packages from the I2P code.
If you have an existing I2P installation and want to use it, you should set
the I2P environment variable to point to your I2P Installation. If you
installed I2P via the .jar, this will be $HOME/i2p. On Apple, the I2P
libraries are found at `/Applications/i2p`. If you have installed I2P using
a Debian package(i.e. `sudo apt-get install i2p i2p-router`) then you have
libraries available at /usr/lib/i2p.
If you have the I2P source code in ../i2p relative to the parent directory,
and have run `ant pkg`, then the libraries will automatically be detected.
./i2p/pkg-tmp
./i2p.plugins.i2psnark-rpc
2. Copy plugin.config from the scripts directory into the plugin directory.
cp scripts/plugin.config plugin/plugin.config
3. If you don't have plugin signing keys yet, the build script will generate them.
However, if you prefer to do this in advance, you can.
To do this with I2P installed in the $HOME directory, you can run the following
script:
java -cp "~/i2p/lib/i2p.jar:/usr/share/java/gnu-getopt.jar" \
net.i2p.crypto.SU3File keygen -t RSA_SHA512_4096 \
"~/.i2p-plugin-keys/user-su3-public-signing.crt" \
"~/.i2p-plugin-keys/user-su3-keystore.ks" \
"user@mail.i2p"
There is a helper script to make this process easier at
[i2pgit.org](https://i2pgit.org/idk/generate-plugin-signing-keys)
[git.idk.i2p](https://i2pgit.org/idk/generate-plugin-signing-keys). If you
have never generated plugin signing keys before, you can run the command:
./i2pk -p $HOME/.i2p-plugin-keys -n 'user' -s 'user@mail.i2p' generate_keys
4. Edit the plugin/plugin.config file. You will need to change the signer field to
match your keys, and add a version line to the file.
name=i2psnark-rpc
-signer=zzz-plugin@mail.i2p
+signer=user@mail.i2p
consoleLinkName=I2PSnark-Remote
consoleLinkURL=/transmission/web/
description=RPC and Web UI for i2psnark
min-java-version=1.7
min-jetty-version=9
min-i2p-version=0.9.47
+version=0.1.2-test
5. You should be ready to build the plugin. Run the script scripts/makeplugin.sh
from the project root.
./scripts/makeplugin.sh
You will be prompted to generate your keystore password. Once entered, the
i2psnark-rpc plugin packages will be generated.

View File

@ -1,3 +1,14 @@
* 2020-06-08 0.6
- Disable pack200
* 2020-05-31 0.5
- Remove bundled libjson-simple which conflicts with i2p.jar
- Switch to use libjson-simple 2.x API in i2p.jar
- Requires I2P 0.9.47
* 2017-03-26 0.4
- Fixes for Sonarr
* 2017-03-23 0.3 * 2017-03-23 0.3
- Implement torrent-add - Implement torrent-add
- Fix stats for magnets and downloads - Fix stats for magnets and downloads

View File

@ -11,7 +11,7 @@
<target name="plugin" depends="war"> <target name="plugin" depends="war">
<!-- get version number --> <!-- get version number -->
<buildnumber file="scripts/build.number" /> <buildnumber file="scripts/build.number" />
<property name="release.number" value="0.3" /> <property name="release.number" value="0.6" />
<!-- we don't bother with an update plugin, everything is in a single war --> <!-- we don't bother with an update plugin, everything is in a single war -->
<copy file="LICENSE.txt" todir="plugin/" overwrite="true" /> <copy file="LICENSE.txt" todir="plugin/" overwrite="true" />
@ -21,8 +21,8 @@
<arg value="version=${release.number}-b${build.number}" /> <arg value="version=${release.number}-b${build.number}" />
</exec> </exec>
<exec executable="pack200" failonerror="true"> <exec executable="pack200" failonerror="true">
<arg value="-g" /> <arg value="-r" />
<arg value="plugin/console/webapps/transmission.war.pack" /> <arg value="plugin/console/webapps/transmission.war" />
<arg value="src/build/transmission.war.jar" /> <arg value="src/build/transmission.war.jar" />
</exec> </exec>
<input message="Enter su3 signing key password:" addproperty="release.password.su3" /> <input message="Enter su3 signing key password:" addproperty="release.password.su3" />
@ -47,7 +47,7 @@
<target name="clean" > <target name="clean" >
<ant dir="src" target="clean" /> <ant dir="src" target="clean" />
<delete file="plugin/plugin.config" /> <delete file="plugin/plugin.config" />
<delete file="plugin/console/webapps/transmission.war.pack" /> <delete file="plugin/console/webapps/transmission.war" />
<delete file="plugin/LICENSE.txt" /> <delete file="plugin/LICENSE.txt" />
<delete file="plugin/README.txt" /> <delete file="plugin/README.txt" />
<delete file="plugin.zip" /> <delete file="plugin.zip" />

View File

@ -1,157 +0,0 @@
**** LICENSING NOTE FROM PARG ****
The version included within Vuze in LGPL version 2.1 and is an old version of the software available here:
https://code.google.com/p/json-simple/downloads/detail?name=json_simple.zip&can=2&q=
(archived here: https://web.archive.org/web/20140328054522/https://json-simple.googlecode.com/files/json_simple.zip )
The license was subsequently updated to Apache but the Vuze copy remains LGPL.
***********************************
Simple Java toolkit for JSON (JSON.simple)
==========================================
1.Why the Simple Java toolkit (also named as JSON.simple) for JSON?
When I use JSON as the data exchange format between the AJAX client and JSP
for the first time, what worry me mostly is how to encode Java strings and
numbers correctly in the server side so the AJAX client will receive a well
formed JSON data. When I looked into the 'JSON in Java' directory in JSON
website,I found that wrappers to JSONObject and JSONArray can be simpler,
due to the simplicity of JSON itself. So I wrote the JSON.simple package.
2.Is it simple,really?
I think so. Take an example:
import org.json.simple.JSONObject;
JSONObject obj=new JSONObject();
obj.put("name","foo");
obj.put("num",new Integer(100));
obj.put("balance",new Double(1000.21));
obj.put("is_vip",new Boolean(true));
obj.put("nickname",null);
System.out.print(obj);
Result:
{"nickname":null,"num":100,"balance":1000.21,"is_vip":true,"name":"foo"}
The JSONObject.toString() will escape controls and specials correctly.
3.How to use JSON.simple in JSP?
Take an example in JSP:
<%@page contentType="text/html; charset=UTF-8"%>
<%@page import="org.json.simple.JSONObject"%>
<%
JSONObject obj=new JSONObject();
obj.put("name","foo");
obj.put("num",new Integer(100));
obj.put("balance",new Double(1000.21));
obj.put("is_vip",new Boolean(true));
obj.put("nickname",null);
out.print(obj);
out.flush();
%>
So the AJAX client will get the responseText.
4.Some details about JSONObject?
JSONObject inherits java.util.HashMap,so it don't have to worry about the
mapping things between keys and values. Feel free to use the Map methods
like get(), put(), and remove() and others. JSONObject.toString() will
combine key value pairs to get the JSON data string. Values will be escaped
into JSON quote string format if it's an instance of java.lang.String. Other
type of instance like java.lang.Number,java.lang.Boolean,null,JSONObject and
JSONArray will NOT escape, just take their java.lang.String.valueOf() result.
null value will be the JSON 'null' in the result.
It's still correct if you put an instance of JSONObject or JSONArray into an
instance of JSONObject or JSONArray. Take the example about:
JSONObject obj2=new JSONObject();
obj2.put("phone","123456");
obj2.put("zip","7890");
obj.put("contact",obj2);
System.out.print(obj);
Result:
{"nickname":null,"num":100,"contact":{"phone":"123456","zip":"7890"},"balance":1000.21,"is_vip":true,"name":"foo"}
The method JSONObject.escape() is used to escape Java string into JSON quote
string. Controls and specials will be escaped correctly into \b,\f,\r,\n,\t,
\",\\,\/,\uhhhh.
5.Some detail about JSONArray?
org.json.simple.JSONArray inherits java.util.ArrayList. Feel free to use the
List methods like get(),add(),remove(),iterator() and so on. The rules of
JSONArray.toString() is similar to JSONObject.toString(). Here's the example:
import org.json.simple.JSONArray;
JSONArray array=new JSONArray();
array.add("hello");
array.add(new Integer(123));
array.add(new Boolean(false));
array.add(null);
array.add(new Double(123.45));
array.add(obj2);//see above
System.out.print(array);
Result:
["hello",123,false,null,123.45,{"phone":"123456","zip":"7890"}]
6.What is JSONValue for?
org.json.simple.JSONValue is use to parse JSON data into Java Object.
In JSON, the topmost entity is JSON value, not the JSON object. But
it's not necessary to wrap JSON string,boolean,number and null again,
for the Java has already had the according classes: java.lang.String,
java.lang.Boolean,java.lang.Number and null. The mapping is:
JSON Java
------------------------------------------------
string <=> java.lang.String
number <=> java.lang.Number
true|false <=> java.lang.Boolean
null <=> null
array <=> org.json.simple.JSONArray
object <=> org.json.simple.JSONObject
------------------------------------------------
JSONValue has only one kind of method, JSONValue.parse(), which receives
a java.io.Reader or java.lang.String. Return type of JSONValue.parse()
is according to the mapping above. If the input is incorrect in syntax or
there's exceptions during the parsing, I choose to return null, ignoring
the exception: I have no idea if it's a serious implementaion, but I think
it's convenient to the user.
Here's the example:
String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]";
Object obj=JSONValue.parse(s);
JSONArray array=(JSONArray)obj;
System.out.println(array.get(1));
JSONObject obj2=(JSONObject)array.get(1);
System.out.println(obj2.get("1"));
Result:
{"1":{"2":{"3":{"4":[5,{"6":7}]}}}}
{"2":{"3":{"4":[5,{"6":7}]}}}
7.About the author.
I'm a Java EE developer on Linux.
I'm working on web systems and information retrieval systems.
I also develop 3D games and Flash games.
You can contact me through:
Fang Yidong<fangyidong@yahoo.com.cn>
Fang Yidong<fangyidng@gmail.com>

View File

@ -7,6 +7,17 @@
# zzz 2010-02 # zzz 2010-02
# zzz 2014-08 added support for su3 files # zzz 2014-08 added support for su3 files
# #
if [ -z "$I2P" -a -d "$PWD/../i2p/pkg-temp" ]; then
export I2P=$PWD/../i2p/pkg-temp
fi
if [ ! -d "$I2P" ]; then
echo "Can't locate your I2P installation. Please add a environment variable named I2P with the path to the folder as value"
echo "On OSX this solved with running: export I2P=/Applications/i2p if default install directory is used."
exit 1
fi
CPATH=$I2P/lib/i2p.jar:/usr/share/java/gnu-getopt.jar CPATH=$I2P/lib/i2p.jar:/usr/share/java/gnu-getopt.jar
PUBKEYDIR=$HOME/.i2p-plugin-keys PUBKEYDIR=$HOME/.i2p-plugin-keys
PUBKEYFILE=$PUBKEYDIR/plugin-public-signing.key PUBKEYFILE=$PUBKEYDIR/plugin-public-signing.key
@ -22,53 +33,53 @@ PLUGINDIR=${1:-plugin}
PC=plugin.config PC=plugin.config
PCT=${PC}.tmp PCT=${PC}.tmp
if [ ! -d $PLUGINDIR ] if [ ! -d "$PLUGINDIR" ]
then then
echo "You must have a $PLUGINDIR directory" echo "You must have a $PLUGINDIR directory"
exit 1 exit 1
fi fi
if [ ! -f $PLUGINDIR/$PC ] if [ ! -f "$PLUGINDIR/$PC" ]
then then
echo "You must have a $PLUGINDIR/$PC file" echo "You must have a $PLUGINDIR/$PC file"
exit 1 exit 1
fi fi
SIGNER=`grep '^signer=' $PLUGINDIR/$PC` SIGNER=`grep '^signer=' "$PLUGINDIR/$PC"`
if [ "$?" -ne "0" ] if [ "$?" -ne "0" ]
then then
echo "You must have a signer name in $PC" echo "You must have a signer name in $PC"
echo 'For example name=foo' echo 'For example signer=foo'
exit 1 exit 1
fi fi
SIGNER=`echo $SIGNER | cut -f 2 -d '='` SIGNER=`echo $SIGNER | cut -f 2 -d '='`
if [ ! -f $PRIVKEYFILE ] if [ ! -f "$PRIVKEYFILE" ]
then then
echo "Creating new XPI2P DSA keys" echo "Creating new XPI2P DSA keys"
mkdir -p $PUBKEYDIR || exit 1 mkdir -p "$PUBKEYDIR" || exit 1
java -cp $CPATH net.i2p.crypto.TrustedUpdate keygen $PUBKEYFILE $PRIVKEYFILE || exit 1 java -cp "$CPATH" net.i2p.crypto.TrustedUpdate keygen "$PUBKEYFILE" "$PRIVKEYFILE" || exit 1
java -cp $CPATH net.i2p.data.Base64 encode $PUBKEYFILE $B64KEYFILE || exit 1 java -cp "$CPATH" net.i2p.data.Base64 encode "$PUBKEYFILE" "$B64KEYFILE" || exit 1
rm -rf logs/ rm -rf logs/
chmod 444 $PUBKEYFILE $B64KEYFILE chmod 444 "$PUBKEYFILE" "$B64KEYFILE"
chmod 400 $PRIVKEYFILE chmod 400 "$PRIVKEYFILE"
echo "Created new XPI2P keys: $PUBKEYFILE $PRIVKEYFILE" echo "Created new XPI2P keys: $PUBKEYFILE $PRIVKEYFILE"
fi fi
if [ ! -f $PRIVKEYSTORE ] if [ ! -f "$PRIVKEYSTORE" ]
then then
echo "Creating new SU3 $KEYTYPE keys for $SIGNER" echo "Creating new SU3 $KEYTYPE keys for $SIGNER"
java -cp $CPATH net.i2p.crypto.SU3File keygen -t $KEYTYPE $PUBKEYSTORE $PRIVKEYSTORE $SIGNER || exit 1 java -cp "$CPATH" net.i2p.crypto.SU3File keygen -t $KEYTYPE "$PUBKEYSTORE" "$PRIVKEYSTORE" $SIGNER || exit 1
echo '*** Save your password in a safe place!!! ***' echo '*** Save your password in a safe place!!! ***'
rm -rf logs/ rm -rf logs/
# copy to the router dir so verify will work # copy to the router dir so verify will work
CDIR=$I2P/certificates/plugin CDIR=$I2P/certificates/plugin
mkdir -p $CDIR || exit 1 mkdir -p "$CDIR" || exit 1
CFILE=$CDIR/`echo $SIGNER | sed s/@/_at_/`.crt CFILE=$CDIR/`echo $SIGNER | sed s/@/_at_/`.crt
cp $PUBKEYSTORE $CFILE cp "$PUBKEYSTORE" "$CFILE"
chmod 444 $PUBKEYSTORE chmod 444 "$PUBKEYSTORE"
chmod 400 $PRIVKEYSTORE chmod 400 "$PRIVKEYSTORE"
chmod 644 $CFILE chmod 644 "$CFILE"
echo "Created new SU3 keys: $PUBKEYSTORE $PRIVKEYSTORE" echo "Created new SU3 keys: $PUBKEYSTORE $PRIVKEYSTORE"
echo "Copied public key to $CFILE for testing" echo "Copied public key to $CFILE for testing"
fi fi
@ -76,7 +87,7 @@ fi
rm -f plugin.zip rm -f plugin.zip
OPWD=$PWD OPWD=$PWD
cd $PLUGINDIR cd "$PLUGINDIR"
grep -q '^name=' $PC grep -q '^name=' $PC
if [ "$?" -ne "0" ] if [ "$?" -ne "0" ]
@ -102,12 +113,12 @@ mv $PCT $PC || exit 1
# add our Base64 key # add our Base64 key
grep -v '^key=' $PC > $PCT grep -v '^key=' $PC > $PCT
B64KEY=`cat $B64KEYFILE` B64KEY=`cat "$B64KEYFILE"`
echo "key=$B64KEY" >> $PCT || exit 1 echo "key=$B64KEY" >> $PCT || exit 1
mv $PCT $PC || exit 1 mv $PCT $PC || exit 1
# zip it # zip it
zip -r $OPWD/plugin.zip * || exit 1 zip -r "$OPWD/plugin.zip" * || exit 1
# get the version and use it for the sud header # get the version and use it for the sud header
VERSION=`grep '^version=' $PC | cut -f 2 -d '='` VERSION=`grep '^version=' $PC | cut -f 2 -d '='`
@ -115,24 +126,24 @@ VERSION=`grep '^version=' $PC | cut -f 2 -d '='`
NAME=`grep '^name=' $PC | cut -f 2 -d '='` NAME=`grep '^name=' $PC | cut -f 2 -d '='`
XPI2P=${NAME}.xpi2p XPI2P=${NAME}.xpi2p
SU3=${NAME}.su3 SU3=${NAME}.su3
cd $OPWD cd "$OPWD"
# sign it # sign it
echo 'Signing. ...' echo 'Signing. ...'
java -cp $CPATH net.i2p.crypto.TrustedUpdate sign plugin.zip $XPI2P $PRIVKEYFILE $VERSION || exit 1 java -cp "$CPATH" net.i2p.crypto.TrustedUpdate sign plugin.zip "$XPI2P" "$PRIVKEYFILE" "$VERSION" || exit 1
java -cp $CPATH net.i2p.crypto.SU3File sign -c PLUGIN -t $KEYTYPE plugin.zip $SU3 $PRIVKEYSTORE $VERSION $SIGNER || exit 1 java -cp "$CPATH" net.i2p.crypto.SU3File sign -c PLUGIN -t $KEYTYPE plugin.zip "$SU3" "$PRIVKEYSTORE" "$VERSION" "$SIGNER" || exit 1
rm -f plugin.zip rm -f plugin.zip
# verify # verify
echo 'Verifying. ...' echo 'Verifying. ...'
java -cp $CPATH net.i2p.crypto.TrustedUpdate showversion $XPI2P || exit 1 java -cp "$CPATH" net.i2p.crypto.TrustedUpdate showversion "$XPI2P" || exit 1
java -cp $CPATH -Drouter.trustedUpdateKeys=$B64KEY net.i2p.crypto.TrustedUpdate verifysig $XPI2P || exit 1 java -cp "$CPATH" -Drouter.trustedUpdateKeys=$B64KEY net.i2p.crypto.TrustedUpdate verifysig "$XPI2P" || exit 1
java -cp $CPATH net.i2p.crypto.SU3File showversion $SU3 || exit 1 java -cp "$CPATH" net.i2p.crypto.SU3File showversion "$SU3" || exit 1
java -cp $CPATH net.i2p.crypto.SU3File verifysig -k $PUBKEYSTORE $SU3 || exit 1 java -cp "$CPATH" net.i2p.crypto.SU3File verifysig -k "$PUBKEYSTORE" "$SU3" || exit 1
rm -rf logs/ rm -rf logs/
echo 'Plugin files created: ' echo 'Plugin files created: '
wc -c $XPI2P wc -c "$XPI2P"
wc -c $SU3 wc -c "$SU3"
exit 0 exit 0

View File

@ -1,6 +1,6 @@
name=i2psnark-rpc name=i2psnark-rpc
signer=zzz-plugin@mail.i2p signer=zzz-plugin@mail.i2p
consoleLinkName=I2PSnark Remote consoleLinkName=I2PSnark-Remote
consoleLinkURL=/transmission/web/ consoleLinkURL=/transmission/web/
description=RPC and Web UI for i2psnark description=RPC and Web UI for i2psnark
author=zzz@mail.i2p author=zzz@mail.i2p
@ -9,4 +9,4 @@ websiteURL=http://zzz.i2p/forums/16
license=GPLv2 license=GPLv2
min-java-version=1.7 min-java-version=1.7
min-jetty-version=9 min-jetty-version=9
min-i2p-version=0.9.29 min-i2p-version=0.9.47

View File

@ -1,205 +0,0 @@
/*
* $Id: ItemList.java,v 1.2 2009-03-15 22:12:18 parg Exp $
* Created on 2006-3-24
*/
package org.json.simple;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
/**
* <20><><EFBFBD><EFBFBD><EFBFBD>÷ָ<C3B7><D6B8><EFBFBD><EFBFBD>ֿ<EFBFBD><D6BF><EFBFBD>һ<EFBFBD><D2BB>item.<2E>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD>һ<EFBFBD><D2BB>item.ÿ<><C3BF>item<65><6D><EFBFBD>߲<EFBFBD><DFB2><EFBFBD><EFBFBD>ǿհ׷<D5B0>.
* <20><><EFBFBD>
* |a:b:c| => |a|,|b|,|c|
* |:| => ||,||
* |a:| => |a|,||
* @author FangYidong<fangyidong@yahoo.com.cn>
*/
public class ItemList {
private final static String sp=",";
List<String> items=new ArrayList<String>();
public ItemList(){}
/**
*
* @param s <20>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
public ItemList(String s){
this.split(s,sp,items);
}
/**
*
* @param s <20>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param sp <20>ָ<EFBFBD><D6B8><EFBFBD>
*/
//public ItemList(String s,String sp){
// this.sp=s;
// this.split(s,sp,items);
//}
/**
*
* @param s
* @param sp
* @param isMultiToken sp<73>Ƿ<EFBFBD>Ϊ<EFBFBD><CEAA>ָ<EFBFBD><D6B8><EFBFBD>
*/
public ItemList(String s,String sp,boolean isMultiToken){
split(s,sp,items,isMultiToken);
}
public List<String> getItems(){
return this.items;
}
public String[] getArray(){
return (String[])this.items.toArray(new String[items.size()]);
}
public void split(String s,String sp,List<String> append,boolean isMultiToken){
if(s==null || sp==null)
return;
if(isMultiToken){
StringTokenizer tokens=new StringTokenizer(s,sp);
while(tokens.hasMoreTokens()){
append.add(tokens.nextToken().trim());
}
}
else{
this.split(s,sp,append);
}
}
public void split(String s,String sp,List<String> append){
if(s==null || sp==null)
return;
int pos=0;
int prevPos=0;
do{
prevPos=pos;
pos=s.indexOf(sp,pos);
if(pos==-1)
break;
append.add(s.substring(prevPos,pos).trim());
pos+=sp.length();
}while(pos!=-1);
append.add(s.substring(prevPos).trim());
}
/**
* <20><><EFBFBD>÷ָ<C3B7><D6B8><EFBFBD>.
* @param sp <20>ָ<EFBFBD><D6B8><EFBFBD>
*/
//public void setSP(String sp){
// this.sp=sp;
//}
/**
* <20><><EFBFBD><EFBFBD><EBB5A5>item.
* @param i <20><><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>(֮ǰ)
* @param item
*/
public void add(int i,String item){
if(item==null)
return;
items.add(i,item.trim());
}
/**
* <20><><EFBFBD><EFBFBD><EBB5A5>item.
* @param item
*/
public void add(String item){
if(item==null)
return;
items.add(item.trim());
}
/**
* <20><>һ<EFBFBD><D2BB>item.
* @param list <20><><EFBFBD><EFBFBD><EFBFBD>list
*/
public void addAll(ItemList list){
items.addAll(list.items);
}
/**
* <20><>һ<EFBFBD><D2BB>item.
* @param s <20>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
public void addAll(String s){
this.split(s,sp,items);
}
/**
* <20><>һ<EFBFBD><D2BB>item.
* @param s <20>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @param sp <20>ָ<EFBFBD><D6B8><EFBFBD>
*/
public void addAll(String s,String sp){
this.split(s,sp,items);
}
public void addAll(String s,String sp,boolean isMultiToken){
this.split(s,sp,items,isMultiToken);
}
/**
* <20><>õ<EFBFBD>i<EFBFBD><69>item. 0-based.
* @param i
* @return
*/
public String get(int i){
return (String)items.get(i);
}
/**
* <20><><EFBFBD>item<65><6D>.
* @return
*/
public int size(){
return items.size();
}
/**
* <20>÷ָ<C3B7><D6B8><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ı<EFBFBD>ʾ.
*/
public String toString(){
return toString(sp);
}
/**
* <20>÷ָ<C3B7><D6B8><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ı<EFBFBD>ʾ.
* @param sp <20><><EFBFBD><EFBFBD>ø÷ָ<C3B7><D6B8><EFBFBD><EFBFBD>ָ<EFBFBD>.
* @return
*/
public String toString(String sp){
StringBuilder sb=new StringBuilder();
for(int i=0;i<items.size();i++){
if(i==0)
sb.append(items.get(i));
else{
sb.append(sp);
sb.append(items.get(i));
}
}
return sb.toString();
}
/**
* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>item.
*/
public void clear(){
items.clear();
}
/**
* <20><>λ.<2E><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݣ<EFBFBD><DDA3><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC>ֵ.
*/
public void reset(){
//sp=",";
items.clear();
}
}

View File

@ -1,72 +0,0 @@
/*
* $Id: JSONArray.java,v 1.1 2007-06-05 00:43:56 tuxpaper Exp $
* Created on 2006-4-10
*/
package org.json.simple;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author FangYidong<fangyidong@yahoo.com.cn>
*/
public class JSONArray extends ArrayList<Object> {
public JSONArray() {
super();
}
public JSONArray(Collection<Object> arg0) {
super(arg0);
}
public JSONArray(int initialCapacity) {
super(initialCapacity);
}
public String toString(){
ItemList list=new ItemList();
Iterator<Object> iter=iterator();
while(iter.hasNext()){
Object value=iter.next();
if(value instanceof String){
list.add("\""+JSONObject.escape((String)value)+"\"");
}
else
list.add(String.valueOf(value));
}
return "["+list.toString()+"]";
}
public void toString( StringBuilder sb ){
sb.append( "[" );
Iterator<Object> iter=iterator();
boolean first = true;
while(iter.hasNext()){
if ( first ){
first = false;
}else{
sb.append( "," );
}
Object value=iter.next();
if(value instanceof String){
sb.append( "\"" );
JSONObject.escape(sb, (String)value);
sb.append( "\"");
}else if ( value instanceof JSONObject ){
((JSONObject)value).toString( sb );
}else if ( value instanceof JSONArray ){
((JSONArray)value).toString( sb );
}else{
sb.append(String.valueOf(value));
}
}
sb.append( "]" );
}
}

View File

@ -1,207 +0,0 @@
/*
* $Id: JSONObject.java,v 1.2 2008-08-07 01:18:54 parg Exp $
* Created on 2006-4-10
*/
package org.json.simple;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* @author FangYidong<fangyidong@yahoo.com.cn>
*/
public class JSONObject extends HashMap<String,Object>{
public JSONObject() {
super();
}
public JSONObject(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
}
public JSONObject(int initialCapacity) {
super(initialCapacity);
}
public JSONObject(Map<String,Object> arg0) {
super(arg0);
}
public String toString(){
ItemList list=new ItemList();
Iterator<Map.Entry<String, Object>> iter=entrySet().iterator();
while(iter.hasNext()){
Map.Entry<String, Object> entry=iter.next();
list.add(toString(entry.getKey().toString(),entry.getValue()));
}
return "{"+list.toString()+"}";
}
public void toString( StringBuilder sb ){
sb.append( "{" );
Iterator iter=entrySet().iterator();
boolean first = true;
while(iter.hasNext()){
if ( first ){
first = false;
}else{
sb.append( "," );
}
Map.Entry entry=(Map.Entry)iter.next();
toString(sb, entry.getKey().toString(),entry.getValue());
}
sb.append( "}" );
}
public static String toString(String key,Object value){
StringBuilder sb=new StringBuilder();
sb.append("\"");
sb.append(escape(key));
sb.append("\":");
if(value==null){
sb.append("null");
return sb.toString();
}
if(value instanceof String){
sb.append("\"");
sb.append(escape((String)value));
sb.append("\"");
}
else
sb.append(value);
return sb.toString();
}
public static void toString(StringBuilder sb, String key,Object value){
sb.append("\"");
escape(sb,key);
sb.append("\":");
if(value==null){
sb.append("null");
return;
}
if(value instanceof String){
sb.append("\"");
escape(sb,(String)value);
sb.append("\"");
}else if ( value instanceof JSONObject ){
((JSONObject)value).toString( sb );
}else if ( value instanceof JSONArray ){
((JSONArray)value).toString( sb );
}else{
sb.append(String.valueOf( value ));
}
}
/**
* " => \" , \ => \\
* @param s
* @return
*/
public static String escape(String s){
if(s==null)
return null;
StringBuilder sb=new StringBuilder();
for(int i=0;i<s.length();i++){
char ch=s.charAt(i);
switch(ch){
case '"':
sb.append("\\\"");
break;
case '\\':
sb.append("\\\\");
break;
case '\b':
sb.append("\\b");
break;
case '\f':
sb.append("\\f");
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\t':
sb.append("\\t");
break;
case '/':
sb.append("\\/");
break;
default:
if(ch>='\u0000' && ch<='\u001F'){
String ss=Integer.toHexString(ch);
sb.append("\\u");
for(int k=0;k<4-ss.length();k++){
sb.append('0');
}
sb.append(ss.toUpperCase());
}
else{
sb.append(ch);
}
}
}//for
return sb.toString();
}
public static void escape(StringBuilder sb, String s){
if(s==null){
sb.append((String)null);
}else{
for(int i=0;i<s.length();i++){
char ch=s.charAt(i);
switch(ch){
case '"':
sb.append("\\\"");
break;
case '\\':
sb.append("\\\\");
break;
case '\b':
sb.append("\\b");
break;
case '\f':
sb.append("\\f");
break;
case '\n':
sb.append("\\n");
break;
case '\r':
sb.append("\\r");
break;
case '\t':
sb.append("\\t");
break;
case '/':
sb.append("\\/");
break;
default:
if(ch>='\u0000' && ch<='\u001F'){
String ss=Integer.toHexString(ch);
sb.append("\\u");
for(int k=0;k<4-ss.length();k++){
sb.append('0');
}
sb.append(ss.toUpperCase());
}
else{
sb.append(ch);
}
}
}//for
}
}
}

View File

@ -1,46 +0,0 @@
/*
* $Id: JSONValue.java,v 1.1 2007-06-05 00:43:56 tuxpaper Exp $
* Created on 2006-4-15
*/
package org.json.simple;
import java.io.Reader;
import java.io.StringReader;
import java.util.Map;
import org.json.simple.parser.JSONParser;
import org.klomp.snark.rpc.JSONUtils;
/**
* @author FangYidong<fangyidong@yahoo.com.cn>
*/
public class JSONValue {
/**
* parse into java object from input source.
* @param in
* @return instance of : JSONObject,JSONArray,String,Boolean,Long,Double or null
*/
public static Object parse(Reader in){
try{
JSONParser parser=new JSONParser();
return parser.parse(in);
}
catch(Exception e){
return null;
}
}
public static Object parse(String s){
StringReader in=new StringReader(s);
return parse(in);
}
public static String toJSONString(Object value) {
if (value instanceof Map) {
return JSONUtils.encodeToJSON((Map) value);
}
return "";
}
}

View File

@ -1,190 +0,0 @@
/*
* $Id: JSONParser.java,v 1.2 2008-08-07 01:18:55 parg Exp $
* Created on 2006-4-15
*/
package org.json.simple.parser;
import java.io.Reader;
import java.util.Stack;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
/**
* @author FangYidong<fangyidong@yahoo.com.cn>
*/
public class JSONParser {
public static final int S_INIT=0;
public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array
public static final int S_IN_OBJECT=2;
public static final int S_IN_ARRAY=3;
public static final int S_PASSED_PAIR_KEY=4;
public static final int S_IN_ERROR=-1;
private int peekStatus(Stack statusStack){
if(statusStack.size()==0)
return -1;
Integer status=(Integer)statusStack.peek();
return status.intValue();
}
public Object parse(Reader in) throws Exception{
Stack statusStack=new Stack();
Stack valueStack=new Stack();
Yylex lexer=new Yylex(in);
Yytoken token=null;
int status=S_INIT;
try{
do{
token=lexer.yylex();
if(token==null)
token=new Yytoken(Yytoken.TYPE_EOF,null);
switch(status){
case S_INIT:
switch(token.type){
case Yytoken.TYPE_VALUE:
status=S_IN_FINISHED_VALUE;
statusStack.push(new Integer(status));
valueStack.push(token.value);
break;
case Yytoken.TYPE_LEFT_BRACE:
status=S_IN_OBJECT;
statusStack.push(new Integer(status));
valueStack.push(new JSONObject());
break;
case Yytoken.TYPE_LEFT_SQUARE:
status=S_IN_ARRAY;
statusStack.push(new Integer(status));
valueStack.push(new JSONArray());
break;
default:
status=S_IN_ERROR;
}//inner switch
break;
case S_IN_FINISHED_VALUE:
if(token.type==Yytoken.TYPE_EOF)
return valueStack.pop();
else
return null;
case S_IN_OBJECT:
switch(token.type){
case Yytoken.TYPE_COMMA:
break;
case Yytoken.TYPE_VALUE:
if(token.value instanceof String){
String key=(String)token.value;
valueStack.push(key);
status=S_PASSED_PAIR_KEY;
statusStack.push(new Integer(status));
}
else{
status=S_IN_ERROR;
}
break;
case Yytoken.TYPE_RIGHT_BRACE:
if(valueStack.size()>1){
statusStack.pop();
JSONObject map = (JSONObject)valueStack.pop();
status=peekStatus(statusStack);
}
else{
status=S_IN_FINISHED_VALUE;
}
break;
default:
status=S_IN_ERROR;
break;
}//inner switch
break;
case S_PASSED_PAIR_KEY:
switch(token.type){
case Yytoken.TYPE_COLON:
break;
case Yytoken.TYPE_VALUE:
statusStack.pop();
String key=(String)valueStack.pop();
JSONObject parent=(JSONObject)valueStack.peek();
parent.put(key,token.value);
status=peekStatus(statusStack);
break;
case Yytoken.TYPE_LEFT_SQUARE:
statusStack.pop();
key=(String)valueStack.pop();
parent=(JSONObject)valueStack.peek();
JSONArray newArray=new JSONArray();
parent.put(key,newArray);
status=S_IN_ARRAY;
statusStack.push(new Integer(status));
valueStack.push(newArray);
break;
case Yytoken.TYPE_LEFT_BRACE:
statusStack.pop();
key=(String)valueStack.pop();
parent=(JSONObject)valueStack.peek();
JSONObject newObject=new JSONObject();
parent.put(key,newObject);
status=S_IN_OBJECT;
statusStack.push(new Integer(status));
valueStack.push(newObject);
break;
default:
status=S_IN_ERROR;
}
break;
case S_IN_ARRAY:
switch(token.type){
case Yytoken.TYPE_COMMA:
break;
case Yytoken.TYPE_VALUE:
JSONArray val=(JSONArray)valueStack.peek();
val.add(token.value);
break;
case Yytoken.TYPE_RIGHT_SQUARE:
if(valueStack.size()>1){
statusStack.pop();
valueStack.pop();
status=peekStatus(statusStack);
}
else{
status=S_IN_FINISHED_VALUE;
}
break;
case Yytoken.TYPE_LEFT_BRACE:
val=(JSONArray)valueStack.peek();
JSONObject newObject=new JSONObject();
val.add(newObject);
status=S_IN_OBJECT;
statusStack.push(new Integer(status));
valueStack.push(newObject);
break;
case Yytoken.TYPE_LEFT_SQUARE:
val=(JSONArray)valueStack.peek();
JSONArray newArray=new JSONArray();
val.add(newArray);
status=S_IN_ARRAY;
statusStack.push(new Integer(status));
valueStack.push(newArray);
break;
default:
status=S_IN_ERROR;
}//inner switch
break;
case S_IN_ERROR:
return null;
}//switch
if(status==S_IN_ERROR)
return null;
}while(token.type!=Yytoken.TYPE_EOF);
}
catch(Exception e){
throw e;
}
return null;
}
}

View File

@ -1,428 +0,0 @@
package org.json.simple.parser;
class Yylex {
private final static int YY_BUFFER_SIZE = 512;
private final static int YY_F = -1;
private final static int YY_NO_STATE = -1;
private final static int YY_NOT_ACCEPT = 0;
//private final static int YY_START = 1;
private final static int YY_END = 2;
private final static int YY_NO_ANCHOR = 4;
private final static int YY_BOL = 65536;
private final static int YY_EOF = 65537;
private StringBuffer sb=new StringBuffer();
private java.io.BufferedReader yy_reader;
private int yy_buffer_index;
private int yy_buffer_read;
private int yy_buffer_start;
private int yy_buffer_end;
private char yy_buffer[];
private boolean yy_at_bol;
private int yy_lexical_state;
Yylex (java.io.Reader reader) {
this ();
if (null == reader) {
throw (new Error("Error: Bad input stream initializer."));
}
yy_reader = new java.io.BufferedReader(reader);
}
Yylex (java.io.InputStream instream) {
this ();
if (null == instream) {
throw (new Error("Error: Bad input stream initializer."));
}
yy_reader = new java.io.BufferedReader(new java.io.InputStreamReader(instream));
}
private Yylex () {
yy_buffer = new char[YY_BUFFER_SIZE];
yy_buffer_read = 0;
yy_buffer_index = 0;
yy_buffer_start = 0;
yy_buffer_end = 0;
yy_at_bol = true;
yy_lexical_state = YYINITIAL;
}
//private boolean yy_eof_done = false;
private static final int YYINITIAL = 0;
private static final int STRING_BEGIN = 1;
private static final int yy_state_dtrans[] = {
0,
39
};
private void yybegin (int state) {
yy_lexical_state = state;
}
private int yy_advance ()
throws java.io.IOException {
int next_read;
int i;
int j;
if (yy_buffer_index < yy_buffer_read) {
return yy_buffer[yy_buffer_index++];
}
if (0 != yy_buffer_start) {
i = yy_buffer_start;
j = 0;
while (i < yy_buffer_read) {
yy_buffer[j] = yy_buffer[i];
++i;
++j;
}
yy_buffer_end = yy_buffer_end - yy_buffer_start;
yy_buffer_start = 0;
yy_buffer_read = j;
yy_buffer_index = j;
next_read = yy_reader.read(yy_buffer,
yy_buffer_read,
yy_buffer.length - yy_buffer_read);
if (-1 == next_read) {
return YY_EOF;
}
yy_buffer_read = yy_buffer_read + next_read;
}
while (yy_buffer_index >= yy_buffer_read) {
if (yy_buffer_index >= yy_buffer.length) {
yy_buffer = yy_double(yy_buffer);
}
next_read = yy_reader.read(yy_buffer,
yy_buffer_read,
yy_buffer.length - yy_buffer_read);
if (-1 == next_read) {
return YY_EOF;
}
yy_buffer_read = yy_buffer_read + next_read;
}
return yy_buffer[yy_buffer_index++];
}
private void yy_move_end () {
if (yy_buffer_end > yy_buffer_start &&
'\n' == yy_buffer[yy_buffer_end-1])
yy_buffer_end--;
if (yy_buffer_end > yy_buffer_start &&
'\r' == yy_buffer[yy_buffer_end-1])
yy_buffer_end--;
}
//private boolean yy_last_was_cr=false;
private void yy_mark_start () {
yy_buffer_start = yy_buffer_index;
}
private void yy_mark_end () {
yy_buffer_end = yy_buffer_index;
}
private void yy_to_mark () {
yy_buffer_index = yy_buffer_end;
yy_at_bol = (yy_buffer_end > yy_buffer_start) &&
('\r' == yy_buffer[yy_buffer_end-1] ||
'\n' == yy_buffer[yy_buffer_end-1] ||
2028/*LS*/ == yy_buffer[yy_buffer_end-1] ||
2029/*PS*/ == yy_buffer[yy_buffer_end-1]);
}
private java.lang.String yytext () {
return (new java.lang.String(yy_buffer,
yy_buffer_start,
yy_buffer_end - yy_buffer_start));
}
//private int yylength () {
// return yy_buffer_end - yy_buffer_start;
//}
private char[] yy_double (char buf[]) {
int i;
char newbuf[];
newbuf = new char[2*buf.length];
for (i = 0; i < buf.length; ++i) {
newbuf[i] = buf[i];
}
return newbuf;
}
private static final int YY_E_INTERNAL = 0;
//private final int YY_E_MATCH = 1;
private java.lang.String yy_error_string[] = {
"Error: Internal error.\n",
"Error: Unmatched input.\n"
};
private void yy_error (int code,boolean fatal) {
java.lang.System.out.print(yy_error_string[code]);
java.lang.System.out.flush();
if (fatal) {
throw new Error("Fatal Error.\n");
}
}
private static int[][] unpackFromString(int size1, int size2, String st) {
int colonIndex = -1;
String lengthString;
int sequenceLength = 0;
int sequenceInteger = 0;
int commaIndex;
String workString;
int res[][] = new int[size1][size2];
for (int i= 0; i < size1; i++) {
for (int j= 0; j < size2; j++) {
if (sequenceLength != 0) {
res[i][j] = sequenceInteger;
sequenceLength--;
continue;
}
commaIndex = st.indexOf(',');
workString = (commaIndex==-1) ? st :
st.substring(0, commaIndex);
st = st.substring(commaIndex+1);
colonIndex = workString.indexOf(':');
if (colonIndex == -1) {
res[i][j]=Integer.parseInt(workString);
continue;
}
lengthString =
workString.substring(colonIndex+1);
sequenceLength=Integer.parseInt(lengthString);
workString=workString.substring(0,colonIndex);
sequenceInteger=Integer.parseInt(workString);
res[i][j] = sequenceInteger;
sequenceLength--;
}
}
return res;
}
private static final int yy_acpt[] = {
/* 0 */ YY_NOT_ACCEPT,
/* 1 */ YY_NO_ANCHOR,
/* 2 */ YY_NO_ANCHOR,
/* 3 */ YY_NO_ANCHOR,
/* 4 */ YY_NO_ANCHOR,
/* 5 */ YY_NO_ANCHOR,
/* 6 */ YY_NO_ANCHOR,
/* 7 */ YY_NO_ANCHOR,
/* 8 */ YY_NO_ANCHOR,
/* 9 */ YY_NO_ANCHOR,
/* 10 */ YY_NO_ANCHOR,
/* 11 */ YY_NO_ANCHOR,
/* 12 */ YY_NO_ANCHOR,
/* 13 */ YY_NO_ANCHOR,
/* 14 */ YY_NO_ANCHOR,
/* 15 */ YY_NO_ANCHOR,
/* 16 */ YY_NO_ANCHOR,
/* 17 */ YY_NO_ANCHOR,
/* 18 */ YY_NO_ANCHOR,
/* 19 */ YY_NO_ANCHOR,
/* 20 */ YY_NO_ANCHOR,
/* 21 */ YY_NO_ANCHOR,
/* 22 */ YY_NO_ANCHOR,
/* 23 */ YY_NO_ANCHOR,
/* 24 */ YY_NO_ANCHOR,
/* 25 */ YY_NOT_ACCEPT,
/* 26 */ YY_NO_ANCHOR,
/* 27 */ YY_NO_ANCHOR,
/* 28 */ YY_NOT_ACCEPT,
/* 29 */ YY_NOT_ACCEPT,
/* 30 */ YY_NOT_ACCEPT,
/* 31 */ YY_NOT_ACCEPT,
/* 32 */ YY_NOT_ACCEPT,
/* 33 */ YY_NOT_ACCEPT,
/* 34 */ YY_NOT_ACCEPT,
/* 35 */ YY_NOT_ACCEPT,
/* 36 */ YY_NOT_ACCEPT,
/* 37 */ YY_NOT_ACCEPT,
/* 38 */ YY_NOT_ACCEPT,
/* 39 */ YY_NOT_ACCEPT,
/* 40 */ YY_NOT_ACCEPT,
/* 41 */ YY_NOT_ACCEPT,
/* 42 */ YY_NOT_ACCEPT,
/* 43 */ YY_NOT_ACCEPT,
/* 44 */ YY_NOT_ACCEPT
};
private static final int yy_cmap[] = unpackFromString(1,65538,
"11:8,27:2,28,11,27,28,11:18,27,11,2,11:8,16,25,12,14,3,13:10,26,11:6,10:4,1" +
"5,10,11:20,23,1,24,11:3,18,4,10:2,17,5,11:5,19,11,6,11:3,7,20,8,9,11:5,21,1" +
"1,22,11:65410,0:2")[0];
private static final int yy_rmap[] = unpackFromString(1,45,
"0,1:2,2,1:7,3,1:2,4,1:10,5,6,1,7,8,9,10,11,12,13,14,15,16,6,17,18,19,20,21," +
"22")[0];
private static final int yy_nxt[][] = unpackFromString(23,29,
"1,-1,2,-1:2,25,28,-1,29,-1:3,30,3,-1:7,4,5,6,7,8,9,10:2,-1:42,3,33,34,-1,34" +
",-1:24,11,-1,34,-1,34,-1:12,16,17,18,19,20,21,22,23,40,-1:37,31,-1:23,26,-1" +
":24,42,-1:26,32,-1:34,3,-1:34,35,-1:18,37,-1:32,11,-1:27,38,26,-1:2,38,-1:3" +
"2,37,-1:27,12,-1:26,13,-1:11,1,14,15,27:25,-1:5,44:2,-1:4,44,-1:2,44,-1,44," +
"-1,44:2,-1:14,24:2,-1:4,24,-1:2,24,-1,24,-1,24:2,-1:29,36,-1:13,41:2,-1:4,4" +
"1,-1:2,41,-1,41,-1,41:2,-1:14,43:2,-1:4,43,-1:2,43,-1,43,-1,43:2,-1:10");
public Yytoken yylex ()
throws java.io.IOException {
int yy_lookahead;
int yy_anchor = YY_NO_ANCHOR;
int yy_state = yy_state_dtrans[yy_lexical_state];
int yy_next_state = YY_NO_STATE;
int yy_last_accept_state = YY_NO_STATE;
boolean yy_initial = true;
int yy_this_accept;
yy_mark_start();
yy_this_accept = yy_acpt[yy_state];
if (YY_NOT_ACCEPT != yy_this_accept) {
yy_last_accept_state = yy_state;
yy_mark_end();
}
while (true) {
if (yy_initial && yy_at_bol) yy_lookahead = YY_BOL;
else yy_lookahead = yy_advance();
yy_next_state = YY_F;
yy_next_state = yy_nxt[yy_rmap[yy_state]][yy_cmap[yy_lookahead]];
if (YY_EOF == yy_lookahead && true == yy_initial) {
return null;
}
if (YY_F != yy_next_state) {
yy_state = yy_next_state;
yy_initial = false;
yy_this_accept = yy_acpt[yy_state];
if (YY_NOT_ACCEPT != yy_this_accept) {
yy_last_accept_state = yy_state;
yy_mark_end();
}
}
else {
if (YY_NO_STATE == yy_last_accept_state) {
throw (new Error("Lexical Error: Unmatched Input."));
}
else {
yy_anchor = yy_acpt[yy_last_accept_state];
if (0 != (YY_END & yy_anchor)) {
yy_move_end();
}
yy_to_mark();
switch (yy_last_accept_state) {
case 1:
case -2:
break;
case 2:
{ sb.delete(0,sb.length());yybegin(STRING_BEGIN);}
case -3:
break;
case 3:
{ Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);}
case -4:
break;
case 4:
{ return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null);}
case -5:
break;
case 5:
{ return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null);}
case -6:
break;
case 6:
{ return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null);}
case -7:
break;
case 7:
{ return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null);}
case -8:
break;
case 8:
{ return new Yytoken(Yytoken.TYPE_COMMA,null);}
case -9:
break;
case 9:
{ return new Yytoken(Yytoken.TYPE_COLON,null);}
case -10:
break;
case 10:
{}
case -11:
break;
case 11:
{ Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);}
case -12:
break;
case 12:
{ return new Yytoken(Yytoken.TYPE_VALUE,null);}
case -13:
break;
case 13:
{ Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);}
case -14:
break;
case 14:
{ sb.append(yytext());}
case -15:
break;
case 15:
{ yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE,sb.toString());}
case -16:
break;
case 16:
{sb.append('\\');}
case -17:
break;
case 17:
{sb.append('"');}
case -18:
break;
case 18:
{sb.append('/');}
case -19:
break;
case 19:
{sb.append('\b');}
case -20:
break;
case 20:
{sb.append('\f');}
case -21:
break;
case 21:
{sb.append('\n');}
case -22:
break;
case 22:
{sb.append('\r');}
case -23:
break;
case 23:
{sb.append('\t');}
case -24:
break;
case 24:
{ int ch=Integer.parseInt(yytext().substring(2),16);
sb.append((char)ch);
}
case -25:
break;
case 26:
{ Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE,val);}
case -26:
break;
case 27:
{ sb.append(yytext());}
case -27:
break;
default:
yy_error(YY_E_INTERNAL,false);
case -1:
}
yy_initial = true;
yy_state = yy_state_dtrans[yy_lexical_state];
yy_next_state = YY_NO_STATE;
yy_last_accept_state = YY_NO_STATE;
yy_mark_start();
yy_this_accept = yy_acpt[yy_state];
if (YY_NOT_ACCEPT != yy_this_accept) {
yy_last_accept_state = yy_state;
yy_mark_end();
}
}
}
}
}
}

View File

@ -1,31 +0,0 @@
/*
* $Id: Yytoken.java,v 1.1 2007-06-05 00:43:56 tuxpaper Exp $
* Created on 2006-4-15
*/
package org.json.simple.parser;
/**
* @author FangYidong<fangyidong@yahoo.com.cn>
*/
public class Yytoken {
public static final int TYPE_VALUE=0;//JSON primitive value: string,number,boolean,null
public static final int TYPE_LEFT_BRACE=1;
public static final int TYPE_RIGHT_BRACE=2;
public static final int TYPE_LEFT_SQUARE=3;
public static final int TYPE_RIGHT_SQUARE=4;
public static final int TYPE_COMMA=5;
public static final int TYPE_COLON=6;
public static final int TYPE_EOF=-1;//end of file
public int type=0;
public Object value=null;
public Yytoken(int type,Object value){
this.type=type;
this.value=value;
}
public String toString(){
return String.valueOf(type+"=>|"+value+"|");
}
}

View File

@ -20,9 +20,9 @@ package org.klomp.snark.rpc;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.*; import java.util.*;
import org.json.simple.JSONArray; import org.json.simple.JsonArray;
import org.json.simple.JSONObject; import org.json.simple.JsonObject;
import org.json.simple.JSONValue; import org.json.simple.Jsoner;
import net.i2p.I2PAppContext; import net.i2p.I2PAppContext;
import net.i2p.data.Base64; import net.i2p.data.Base64;
@ -47,7 +47,7 @@ public class JSONUtils
*/ */
public static Map decodeJSON(String json) { public static Map decodeJSON(String json) {
try { try {
Object object = JSONValue.parse(json); Object object = Jsoner.deserialize(json);
if (object instanceof Map) { if (object instanceof Map) {
return (Map) object; return (Map) object;
} }
@ -62,7 +62,7 @@ public class JSONUtils
} }
/** /**
* encodes a map into a JSONObject. * encodes a map into a JsonObject.
* <P> * <P>
* It's recommended that you use {@link #encodeToJSON(Map)} instead * It's recommended that you use {@link #encodeToJSON(Map)} instead
* *
@ -71,8 +71,8 @@ public class JSONUtils
* *
* @since 3.0.1.5 * @since 3.0.1.5
*/ */
public static JSONObject encodeToJSONObject(Map map) { public static JsonObject encodeToJSONObject(Map map) {
JSONObject newMap = new JSONObject((int)(map.size()*1.5)); JsonObject newMap = new JsonObject();
for (Map.Entry<String, Object> entry: ((Map<String,Object>)map).entrySet()){ for (Map.Entry<String, Object> entry: ((Map<String,Object>)map).entrySet()){
String key = entry.getKey(); String key = entry.getKey();
@ -99,14 +99,12 @@ public class JSONUtils
* @since 3.0.1.5 * @since 3.0.1.5
*/ */
public static String encodeToJSON(Map map) { public static String encodeToJSON(Map map) {
JSONObject jobj = encodeToJSONObject(map); JsonObject jobj = encodeToJSONObject(map);
StringBuilder sb = new StringBuilder(8192); return jobj.toJson();
jobj.toString( sb );
return( sb.toString());
} }
public static String encodeToJSON(Collection list) { public static String encodeToJSON(Collection list) {
return encodeToJSONArray(list).toString(); return encodeToJSONArray(list).toJson();
} }
private static Object coerce(Object value) { private static Object coerce(Object value) {
@ -153,8 +151,8 @@ public class JSONUtils
* *
* @since 3.0.1.5 * @since 3.0.1.5
*/ */
private static JSONArray encodeToJSONArray(Collection list) { private static JsonArray encodeToJSONArray(Collection list) {
JSONArray newList = new JSONArray(list.size()); JsonArray newList = new JsonArray();
for ( Object value: list ){ for ( Object value: list ){
newList.add(coerce(value)); newList.add(coerce(value));
} }

View File

@ -24,6 +24,13 @@ public class RPCServlet extends HttpServlet {
private SnarkManager _manager; private SnarkManager _manager;
private XMWebUIPlugin _plugin; private XMWebUIPlugin _plugin;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// Sonarr does a GET to test,
// pass it through so it will get the 409 response
doPost(req, resp);
}
@Override @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
XMWebUIPlugin plugin; XMWebUIPlugin plugin;

View File

@ -80,8 +80,7 @@ import org.klomp.snark.Storage;
import org.klomp.snark.TrackerClient; import org.klomp.snark.TrackerClient;
import org.klomp.snark.bencode.BEncoder; import org.klomp.snark.bencode.BEncoder;
import org.json.simple.JSONObject; import org.json.simple.JsonObject;
import org.json.simple.JSONValue;
@SuppressWarnings({ @SuppressWarnings({
"unchecked", "unchecked",
@ -425,7 +424,7 @@ XMWebUIPlugin {
generateSupport(HttpServletRequest request, HttpServletResponse response) throws IOException { generateSupport(HttpServletRequest request, HttpServletResponse response) throws IOException {
boolean logit = trace_param; boolean logit = trace_param;
if (logit) { if (logit) {
log("-> " + request.getServletPath()); log("-> " + request.getMethod() + ' ' + request.getServletPath());
String qs = request.getQueryString(); String qs = request.getQueryString();
if (qs != null) if (qs != null)
log( "-> query: " + qs); log( "-> query: " + qs);
@ -440,10 +439,6 @@ XMWebUIPlugin {
response.setStatus( 415 ); response.setStatus( 415 );
return true; return true;
} }
if (!request.getMethod().equals("POST")) {
response.setStatus( 405 );
return true;
}
try { try {
String session_id = getSessionID( request ); String session_id = getSessionID( request );
// Set cookie just in case client is looking for one.. // Set cookie just in case client is looking for one..
@ -458,6 +453,12 @@ XMWebUIPlugin {
response.getOutputStream().write("You_didn_t_set_the_X-Transmission-Session-Id".getBytes()); response.getOutputStream().write("You_didn_t_set_the_X-Transmission-Session-Id".getBytes());
return true; return true;
} }
if (!request.getMethod().equals("POST")) {
// Sonarr does a GET for testing and to get the 409, shouldn't go past here
response.setContentType("text/plain; charset=UTF-8");
response.setStatus(200);
return true;
}
String session_id_plus = session_id; String session_id_plus = session_id;
// XXX getHeaders() keys are lowercase.. this line always null? // XXX getHeaders() keys are lowercase.. this line always null?
String tid = request.getHeader( "X-XMRPC-Tunnel-ID" ); String tid = request.getHeader( "X-XMRPC-Tunnel-ID" );
@ -1187,7 +1188,7 @@ XMWebUIPlugin {
List<Map> l_engines = new ArrayList<Map>(); List<Map> l_engines = new ArrayList<Map>();
result.put("engines", l_engines); result.put("engines", l_engines);
for (Engine engine : engines) { for (Engine engine : engines) {
JSONObject map = new JSONObject(); JsonObject map = new JsonObject();
l_engines.add(map); l_engines.add(map);
map.put("name", engine.getName()); map.put("name", engine.getName());
map.put("id", engine.getUID()); map.put("id", engine.getUID());
@ -1925,7 +1926,8 @@ XMWebUIPlugin {
result.put( "rpc-version-minimum", Long.valueOf(6)); // number the minimum RPC API version supported result.put( "rpc-version-minimum", Long.valueOf(6)); // number the minimum RPC API version supported
result.put( "seedRatioLimit", Double.valueOf(100.0) ); // double the default seed ratio for torrents to use result.put( "seedRatioLimit", Double.valueOf(100.0) ); // double the default seed ratio for torrents to use
result.put( "seedRatioLimited", Boolean.FALSE ); // boolean true if seedRatioLimit is honored by default result.put( "seedRatioLimited", Boolean.FALSE ); // boolean true if seedRatioLimit is honored by default
result.put( "version", CoreVersion.VERSION); // string result.put( "version", "2.80"); // This must match the RPC API from the spec to make Sonarr happy
result.put( "i2p-version", CoreVersion.VERSION); // unused
result.put( "az-rpc-version", VUZE_RPC_VERSION); result.put( "az-rpc-version", VUZE_RPC_VERSION);
result.put( "az-version", az_version ); // string result.put( "az-version", az_version ); // string
result.put( "az-mode", az_mode ); // string result.put( "az-mode", az_mode ); // string

View File

@ -1,6 +1,6 @@
<html> <html>
<body> <body>
<h2>i2psnark-rpc Plugin Version 0.3</h2> <h2>i2psnark-rpc Plugin Version 0.4</h2>
<p> <p>
This is a Transmission- and Vuze- compatible RPC server for i2psnark, This is a Transmission- and Vuze- compatible RPC server for i2psnark,
with the Vuze-modified Transmission web UI. with the Vuze-modified Transmission web UI.
@ -16,6 +16,11 @@ specify port 7657. For example, to list the torrents:
transmission-remote 7657 -l transmission-remote 7657 -l
</pre> </pre>
<p>
For <a href="https://sonarr.tv/">Sonarr</a>:
Settings -&gt; Download Client -&gt click "+" -&gt; click "Transmission" -&gt; change port to 7657 and click "Save"
<p> <p>
Most basic features are supported. Several advanced features are not supported. Most basic features are supported. Several advanced features are not supported.
Some may be added in a future release. Some may be added in a future release.

View File

@ -35,13 +35,6 @@ Copyright (c) Transmission authors and contributors
<br> <br>
See <a href="licenses/Transmission.txt">Transmission.txt</a> See <a href="licenses/Transmission.txt">Transmission.txt</a>
<p>
JSON:
<br>
LGPLv2.1
<br>
See <a href="licenses/JSON.txt">JSON.txt</a>
<p> <p>
Transmission/Vuze web UI: Transmission/Vuze web UI:
<br> <br>