1
0
mirror of https://github.com/Rogiel/httpchannel synced 2025-12-05 23:22:51 +00:00

Implements CaptchaTrader service

This commit is contained in:
2012-01-17 12:28:22 -02:00
parent e943b08ede
commit 08d22a12fe
81 changed files with 2750 additions and 543 deletions

View File

@@ -9,25 +9,45 @@ package com.rogiel.httpchannel.captcha;
*/
public interface Captcha {
/**
* Sets the captcha answer
*
* @return the captcha ID
*/
String getID();
/**
* @return the resolved captcha answer
*/
String getAnswer();
/**
* @param answer
* the captcha answer
*/
void setAnswer(String answer);
/**
* Returns the captcha answer. <code>null</code> if the service was not able
* to resolve it automatically. In such case, {@link #setAnswer(String)}
* must be used to set the correct answer.
*
* @return the captcha answer
* @return <code>true</code> if the captcha was resolved and
* {@link #getAnswer()} will not return <code>null</code>.
*/
String getAnswer();
boolean isResolved();
/**
* @return <code>true</code> if, and only if, the service was able to
* automatically resolve the captcha result
* Get this CAPTCHA's attachment.
* <p>
* <b>Important note</b>: Attachments are for {@link CaptchaService}
* implementations usage! You should not touch any of the attachments!
*
* @return the attachment
*/
boolean wasAutomaticallyResolved();
Object getAttachment();
/**
* Sets this CAPTCHA's attachment.
* <p>
* <b>Important note</b>: Attachments are for {@link CaptchaService}
* implementations usage! You should not touch any of the attachments!
*
* @param attachment
* the attachment
*/
void setAttachment(Object attachment);
}

View File

@@ -1,19 +0,0 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface CaptchaResolver {
/**
* Tries to resolve the captcha
*
* @param captcha
* the captcha
* @return <code>true</code> if the captcha was resolve, <code>false</code>
* to abort
*/
boolean resolve(Captcha captcha);
}

View File

@@ -3,9 +3,52 @@
*/
package com.rogiel.httpchannel.captcha;
import com.rogiel.httpchannel.captcha.exception.AuthenticationCaptchaServiceException;
import com.rogiel.httpchannel.captcha.exception.InvalidCaptchaServiceException;
import com.rogiel.httpchannel.captcha.exception.UnsolvableCaptchaServiceException;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface CaptchaService<C extends Captcha> {
/**
* Authenticates the service instance into the CAPTCHA solving server, if
* any. Implementations that do not use authentication, should do nothing
* and return <code>-1</code>
*
* @param username
* @param password
* @return amount of remaining CAPTCHA solving, <code>-1</code> if no limit
* is applied
*/
int authenticate(String username, String password)
throws AuthenticationCaptchaServiceException;
/**
* Tries to resolve the captcha and returns the correct answer.
*
* @param captcha
* @throws UnsolvableCaptchaServiceException
* if the CAPTCHA could not be solved by the service
*/
void solve(C captcha) throws UnsolvableCaptchaServiceException;
/**
* Notifies the service that the given captcha answer was correct
*
* @param captcha
* the captcha
* @throws InvalidCaptchaServiceException
* normally thrown if the CAPTCHA was not solved by this service
*/
void valid(C captcha) throws InvalidCaptchaServiceException;
/**
* Notifies the service that the given captcha answer was incorrect
*
* @param captcha
* @throws InvalidCaptchaServiceException
* normally thrown if the CAPTCHA was not solved by this service
*/
void invalid(C captcha) throws InvalidCaptchaServiceException;
}

View File

@@ -9,14 +9,66 @@ import java.net.URL;
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface ImageCaptcha extends Captcha {
public class ImageCaptcha implements Captcha {
/**
* @return the captcha identifier
* The CAPTCHA ID
*/
String getID();
private final String ID;
/**
* The CAPTCHA Image {@link URL}
*/
private final URL imageURL;
/**
* The CAPTCHA answer
*/
private String answer;
/**
* The CAPTCHA attachment
*/
private Object attachment;
/**
* @return the captcha image {@link URL}
*/
URL getImageURL();
public ImageCaptcha(String id, URL imageURL) {
this.ID = id;
this.imageURL = imageURL;
}
@Override
public String getID() {
return ID;
}
public URL getImageURL() {
return imageURL;
}
@Override
public String getAnswer() {
return answer;
}
@Override
public void setAnswer(String answer) {
this.answer = answer;
}
@Override
public boolean isResolved() {
return answer != null;
}
@Override
public Object getAttachment() {
return attachment;
}
@Override
public void setAttachment(Object attachment) {
this.attachment = attachment;
}
@Override
public String toString() {
return "ImageCaptcha [ID=" + ID + ", imageURL=" + imageURL
+ ", answer=" + answer + ", attachment=" + attachment + "]";
}
}

View File

@@ -3,32 +3,10 @@
*/
package com.rogiel.httpchannel.captcha;
import java.net.MalformedURLException;
import java.net.URL;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface ImageCaptchaService<C extends ImageCaptcha> extends
CaptchaService<C> {
/**
* Creates a new captcha from the given HTML content
*
* @param image
* the image {@link URL}
* @return a new captcha
* @throws MalformedURLException
* if any error occur while creating the Image {@link URL}
*/
C create(String html) throws MalformedURLException;
public interface ImageCaptchaService extends CaptchaService<ImageCaptcha> {
/**
* Tries to automatically resolve the captcha
*
* @param captcha
* the captcha to be resolved
* @return <code>true</code> if the captcha was successfully resolved
*/
boolean resolve(C captcha);
}

View File

@@ -0,0 +1,49 @@
/**
*
*/
package com.rogiel.httpchannel.captcha.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class AuthenticationCaptchaServiceException extends CaptchaServiceException {
/**
* The Java Serialization API ID
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new instance
*/
public AuthenticationCaptchaServiceException() {
}
/**
* @param message
* the message
* @param cause
* the cause
*/
public AuthenticationCaptchaServiceException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public AuthenticationCaptchaServiceException(String message) {
super(message);
}
/**
* @param cause
* the cause
*/
public AuthenticationCaptchaServiceException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,50 @@
/**
*
*/
package com.rogiel.httpchannel.captcha.exception;
import com.rogiel.httpchannel.service.exception.ChannelServiceException;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class CaptchaServiceException extends ChannelServiceException {
/**
* The Java Serialization API ID
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new instance
*/
public CaptchaServiceException() {
}
/**
* @param message
* the message
* @param cause
* the cause
*/
public CaptchaServiceException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public CaptchaServiceException(String message) {
super(message);
}
/**
* @param cause
* the cause
*/
public CaptchaServiceException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,49 @@
/**
*
*/
package com.rogiel.httpchannel.captcha.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class InvalidCaptchaServiceException extends CaptchaServiceException {
/**
* The Java Serialization API ID
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new instance
*/
public InvalidCaptchaServiceException() {
}
/**
* @param message
* the message
* @param cause
* the cause
*/
public InvalidCaptchaServiceException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public InvalidCaptchaServiceException(String message) {
super(message);
}
/**
* @param cause
* the cause
*/
public InvalidCaptchaServiceException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,49 @@
/**
*
*/
package com.rogiel.httpchannel.captcha.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class UnsolvableCaptchaServiceException extends CaptchaServiceException {
/**
* The Java Serialization API ID
*/
private static final long serialVersionUID = 1L;
/**
* Creates a new instance
*/
public UnsolvableCaptchaServiceException() {
}
/**
* @param message
* the message
* @param cause
* the cause
*/
public UnsolvableCaptchaServiceException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public UnsolvableCaptchaServiceException(String message) {
super(message);
}
/**
* @param cause
* the cause
*/
public UnsolvableCaptchaServiceException(Throwable cause) {
super(cause);
}
}

View File

@@ -16,9 +16,13 @@
*/
package com.rogiel.httpchannel.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.rogiel.httpchannel.captcha.Captcha;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
import com.rogiel.httpchannel.service.exception.UnresolvedCaptchaException;
import com.rogiel.httpchannel.captcha.CaptchaService;
import com.rogiel.httpchannel.captcha.exception.UnsolvableCaptchaServiceException;
import com.rogiel.httpchannel.service.exception.NoCaptchaServiceException;
/**
* This is an abstract {@link Service} implementation.
@@ -27,7 +31,11 @@ import com.rogiel.httpchannel.service.exception.UnresolvedCaptchaException;
* @version 1.0
*/
public abstract class AbstractService implements Service {
protected CaptchaResolver captchaResolver;
/**
* The service {@link Logger} instance
*/
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
protected CaptchaService<Captcha> captchaService;
@Override
public Service clone() {
@@ -39,17 +47,17 @@ public abstract class AbstractService implements Service {
}
@Override
public void setCaptchaResolver(CaptchaResolver captchaResolver) {
this.captchaResolver = captchaResolver;
@SuppressWarnings("unchecked")
public void setCaptchaService(
CaptchaService<? extends Captcha> captchaService) {
this.captchaService = (CaptchaService<Captcha>) captchaService;
}
protected void resolveCaptcha(Captcha captcha)
throws UnresolvedCaptchaException {
if (captchaResolver == null)
throw new UnresolvedCaptchaException();
if (!captchaResolver.resolve(captcha))
throw new UnresolvedCaptchaException();
if (captcha.getAnswer() == null)
throw new UnresolvedCaptchaException();
throws NoCaptchaServiceException, UnsolvableCaptchaServiceException {
if (captchaService == null)
throw new NoCaptchaServiceException(
"No CaptchaService is configured");
captchaService.solve((Captcha) captcha);
}
}

View File

@@ -18,10 +18,11 @@ package com.rogiel.httpchannel.service;
import java.io.IOException;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
import com.rogiel.httpchannel.captcha.CaptchaService;
import com.rogiel.httpchannel.captcha.exception.UnsolvableCaptchaServiceException;
import com.rogiel.httpchannel.service.Authenticator.AuthenticatorConfiguration;
import com.rogiel.httpchannel.service.exception.AuthenticationInvalidCredentialException;
import com.rogiel.httpchannel.service.exception.UnresolvedCaptchaException;
import com.rogiel.httpchannel.service.exception.NoCaptchaServiceException;
/**
* This interfaces provides authentication for an service.
@@ -40,13 +41,16 @@ public interface Authenticator<C extends AuthenticatorConfiguration> {
* if any IO error occur
* @throws AuthenticationInvalidCredentialException
* if the credentials are not valid or cannot be used
* @throws UnresolvedCaptchaException
* @throws UnsolvableCaptchaServiceException
* if the service required captcha resolving but no
* {@link CaptchaResolver} was available or the resolver did not
* {@link CaptchaService} was available or the service did not
* solve the challenge
* @throws NoCaptchaServiceException
* if the service required an {@link CaptchaService}
* implementation to be present, but none was available
*/
void login() throws IOException, AuthenticationInvalidCredentialException,
UnresolvedCaptchaException;
UnsolvableCaptchaServiceException, NoCaptchaServiceException;
/**
* Logout into the {@link Service}. The session is restored to an not

View File

@@ -32,13 +32,4 @@ import java.nio.channels.ReadableByteChannel;
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface DownloadChannel extends HttpChannel, ReadableByteChannel {
/**
* @return the file size
*/
long getFilesize();
/**
* @return the file name
*/
String getFilename();
}

View File

@@ -18,13 +18,14 @@ package com.rogiel.httpchannel.service;
import java.io.IOException;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
import com.rogiel.httpchannel.captcha.CaptchaService;
import com.rogiel.httpchannel.captcha.exception.UnsolvableCaptchaServiceException;
import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
import com.rogiel.httpchannel.service.exception.DownloadLimitExceededException;
import com.rogiel.httpchannel.service.exception.DownloadLinkNotFoundException;
import com.rogiel.httpchannel.service.exception.DownloadNotAuthorizedException;
import com.rogiel.httpchannel.service.exception.DownloadNotResumableException;
import com.rogiel.httpchannel.service.exception.UnresolvedCaptchaException;
import com.rogiel.httpchannel.service.exception.NoCaptchaServiceException;
/**
* This interfaces provides downloading for an service.
@@ -42,7 +43,8 @@ public interface Downloader<C extends DownloaderConfiguration> {
* very unlikely to be done. The most common usage usage scenario for this
* is when an {@link DownloadNotResumableException} is thrown and you wish
* to restart the download from start giving <tt>position</tt> equal to
* zero.
* zero, in such scenario, reutilizing the same {@link Downloader} instance
* is safe.
* <p>
* Please remember to close the channel by calling
* {@link DownloadChannel#close()}, otherwise some of the resources (such as
@@ -70,15 +72,19 @@ public interface Downloader<C extends DownloaderConfiguration> {
* @throws DownloadNotResumableException
* if the download cannot be started at <tt>position</tt>. Will
* only be thrown if <tt>position > 0</tt>.
* @throws UnresolvedCaptchaException
* @throws UnsolvableCaptchaServiceException
* if the service required captcha resolving but no
* {@link CaptchaResolver} was available or the resolver did not
* {@link CaptchaService} was available or the service did not
* solve the challenge
* @throws NoCaptchaServiceException
* if the service required an {@link CaptchaService}
* implementation to be present, but none was available
*/
DownloadChannel openChannel(DownloadListener listener, long position)
throws IOException, DownloadLinkNotFoundException,
DownloadLimitExceededException, DownloadNotAuthorizedException,
DownloadNotResumableException, UnresolvedCaptchaException;
DownloadNotResumableException, UnsolvableCaptchaServiceException,
NoCaptchaServiceException;
/**
* Opens a new {@link DownloadChannel} with not listener. For more details,
@@ -102,14 +108,26 @@ public interface Downloader<C extends DownloaderConfiguration> {
* @throws DownloadNotResumableException
* if the download cannot be started at <tt>position</tt>. Will
* only be thrown if <tt>position > 0</tt>.
* @throws UnsolvableCaptchaServiceException
* if the service required captcha resolving but no
* {@link CaptchaService} was available or the service did not
* solve the challenge
* @throws NoCaptchaServiceException
* if the service required an {@link CaptchaService}
* implementation to be present, but none was available
*
*/
DownloadChannel openChannel(long position) throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException,
DownloadNotAuthorizedException, DownloadNotResumableException;
DownloadNotAuthorizedException, DownloadNotResumableException,
UnsolvableCaptchaServiceException, NoCaptchaServiceException;
/**
* Opens a new {@link DownloadChannel} positioned at start. For more
* details, see {@link #openChannel(DownloadListener, long)}
* <p>
* Note that {@link DownloadNotResumableException} is never thrown because
* this channel always starts at <code>0</code> offset.
*
* @param listener
* the listener to keep a track on the download progress
@@ -125,14 +143,25 @@ public interface Downloader<C extends DownloaderConfiguration> {
* @throws DownloadNotAuthorizedException
* if the user (or guest) account does not have necessary rights
* to download the file
* @throws UnsolvableCaptchaServiceException
* if the service required captcha resolving but no
* {@link CaptchaService} was available or the service did not
* solve the challenge
* @throws NoCaptchaServiceException
* if the service required an {@link CaptchaService}
* implementation to be present, but none was available
*/
DownloadChannel openChannel(DownloadListener listener) throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException,
DownloadNotAuthorizedException;
DownloadNotAuthorizedException, UnsolvableCaptchaServiceException,
NoCaptchaServiceException;
/**
* Opens a new {@link DownloadChannel} with not listener and positioned at
* start. For more details, see {@link #openChannel(DownloadListener, long)}
* <p>
* Note that {@link DownloadNotResumableException} is never thrown because
* this channel always starts at <code>0</code> offset.
*
* @return the {@link DownloadChannel} instance
* @throws IOException
@@ -146,10 +175,18 @@ public interface Downloader<C extends DownloaderConfiguration> {
* @throws DownloadNotAuthorizedException
* if the user (or guest) account does not have necessary rights
* to download the file
* @throws UnsolvableCaptchaServiceException
* if the service required captcha resolving but no
* {@link CaptchaService} was available or the service did not
* solve the challenge
* @throws NoCaptchaServiceException
* if the service required an {@link CaptchaService}
* implementation to be present, but none was available
*/
DownloadChannel openChannel() throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException,
DownloadNotAuthorizedException;
DownloadNotAuthorizedException, UnsolvableCaptchaServiceException,
NoCaptchaServiceException;
/**
* Returns this {@link Downloader} configuration.

View File

@@ -0,0 +1,23 @@
/**
*
*/
package com.rogiel.httpchannel.service;
import java.io.Closeable;
import java.nio.channels.Channel;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public interface HttpChannel extends Channel, Closeable {
/**
* @return the file size
*/
long getFilesize();
/**
* @return the file name
*/
String getFilename();
}

View File

@@ -16,7 +16,8 @@
*/
package com.rogiel.httpchannel.service;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
import com.rogiel.httpchannel.captcha.Captcha;
import com.rogiel.httpchannel.captcha.CaptchaService;
/**
* Base interface for all the services. Whenever the operation suported by the
@@ -53,13 +54,13 @@ public interface Service extends Cloneable {
int getMinorVersion();
/**
* Sets this service captcha resolver. Resolvers are safe to be switched
* Sets this service captcha service. CaptchaService are safe to be switched
* even after an transfer has begun.
*
* @param resolver
* the captcha resolver
* @param captchaService
* the captcha service
*/
void setCaptchaResolver(CaptchaResolver resolver);
void setCaptchaService(CaptchaService<? extends Captcha> captchaService);
/**
* @return a cloned version of this service

View File

@@ -36,16 +36,6 @@ import com.rogiel.httpchannel.service.exception.UploadLinkNotFoundException;
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface UploadChannel extends HttpChannel, WritableByteChannel {
/**
* @return the file size
*/
long getFilesize();
/**
* @return the file name
*/
String getFilename();
/**
* The link is located after you call {@link UploadChannel#close()}, but it
* can only be retrieved by calling this method. If {@link #close()} throwed

View File

@@ -18,9 +18,10 @@ package com.rogiel.httpchannel.service;
import java.io.IOException;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
import com.rogiel.httpchannel.captcha.CaptchaService;
import com.rogiel.httpchannel.captcha.exception.UnsolvableCaptchaServiceException;
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
import com.rogiel.httpchannel.service.exception.UnresolvedCaptchaException;
import com.rogiel.httpchannel.service.exception.NoCaptchaServiceException;
/**
* This interfaces provides uploading for an service.
@@ -48,12 +49,16 @@ public interface Uploader<C extends UploaderConfiguration> {
* @return the {@link UploadChannel} instance
* @throws IOException
* if any IO error occur
* @throws UnresolvedCaptchaException
* @throws UnsolvableCaptchaServiceException
* if the service required captcha resolving but no
* {@link CaptchaResolver} was available or the resolver did not
* {@link CaptchaService} was available or the service did not
* solve the challenge
* @throws NoCaptchaServiceException
* if the service required an {@link CaptchaService}
* implementation to be present, but none was available
*/
UploadChannel openChannel() throws IOException, UnresolvedCaptchaException;
UploadChannel openChannel() throws IOException,
UnsolvableCaptchaServiceException, NoCaptchaServiceException;
/**
* Returns this {@link Uploader} configuration.

View File

@@ -16,10 +16,10 @@
*/
package com.rogiel.httpchannel.service.exception;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
import com.rogiel.httpchannel.captcha.CaptchaService;
/**
* Exception thrown if the {@link CaptchaResolver} has returned an invalid
* Exception thrown if the {@link CaptchaService} has returned an invalid
* captcha
*
* @author <a href="http://www.rogiel.com">Rogiel</a>

View File

@@ -16,21 +16,21 @@
*/
package com.rogiel.httpchannel.service.exception;
import com.rogiel.httpchannel.captcha.CaptchaResolver;
import com.rogiel.httpchannel.captcha.CaptchaService;
/**
* Exception thrown if the {@link CaptchaResolver} has returned an invalid
* Exception thrown if the {@link CaptchaService} has returned an invalid
* captcha
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class UnresolvedCaptchaException extends ChannelServiceException {
public class NoCaptchaServiceException extends ChannelServiceException {
private static final long serialVersionUID = 1L;
/**
* Creates a new empty instance of this exception
*/
public UnresolvedCaptchaException() {
public NoCaptchaServiceException() {
super();
}
@@ -40,7 +40,7 @@ public class UnresolvedCaptchaException extends ChannelServiceException {
* @param cause
* the root cause
*/
public UnresolvedCaptchaException(String message, Throwable cause) {
public NoCaptchaServiceException(String message, Throwable cause) {
super(message, cause);
}
@@ -48,7 +48,7 @@ public class UnresolvedCaptchaException extends ChannelServiceException {
* @param message
* the message
*/
public UnresolvedCaptchaException(String message) {
public NoCaptchaServiceException(String message) {
super(message);
}
@@ -56,7 +56,7 @@ public class UnresolvedCaptchaException extends ChannelServiceException {
* @param cause
* the root cause
*/
public UnresolvedCaptchaException(Throwable cause) {
public NoCaptchaServiceException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,49 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>httpchannel-captcha</artifactId>
<groupId>com.rogiel.httpchannel</groupId>
<version>1.0.0</version>
<relativePath>..</relativePath>
</parent>
<groupId>com.rogiel.httpchannel.captcha</groupId>
<artifactId>httpchannel-captcha-captchatrader</artifactId>
<name>HttpChannel/Captcha/CaptchaTrader</name>
<description>This module provides an CaptchService that resolves image captchas.</description>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.1.2</version>
<type>jar</type>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,207 @@
/**
*
*/
package com.captchatrader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.omg.CORBA.Any;
import com.captchatrader.exception.ApplicationKeyDisabledException;
import com.captchatrader.exception.CaptchaTraderException;
import com.captchatrader.exception.ConnectionLimitException;
import com.captchatrader.exception.DailyLimitException;
import com.captchatrader.exception.ImageTooLargeException;
import com.captchatrader.exception.IncorrectRespondsException;
import com.captchatrader.exception.InsuficientCreditsException;
import com.captchatrader.exception.InternalErrorException;
import com.captchatrader.exception.InvalidApplicationKeyException;
import com.captchatrader.exception.InvalidParametersException;
import com.captchatrader.exception.InvalidTicketException;
import com.captchatrader.exception.InvalidURLException;
import com.captchatrader.exception.InvalidUserException;
import com.captchatrader.exception.NotAnImageException;
import com.captchatrader.exception.SubmissionErrorException;
import com.captchatrader.exception.UserNotValidatedException;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class CaptchaTrader {
/**
* The {@link HttpClient} instance
*/
private final HttpClient client = new DefaultHttpClient();
private final JSONParser json = new JSONParser();
private final URI apiURL;
private final String applicationKey;
private final String username;
private final String password;
/**
* Creates a new API instance with the given application key
*
* @param applicationKey
* the key
*/
public CaptchaTrader(URI apiURL, String applicationKey, String username,
String password) {
this.apiURL = apiURL;
this.applicationKey = applicationKey;
this.username = username;
this.password = password;
}
/**
* Creates a new API instance with the given application key
*
* @param applicationKey
* the key
* @throws MalformedURLException
*/
public CaptchaTrader(String applicationKey, String username, String password) {
this(URI.create("http://api.captchatrader.com/"), applicationKey,
username, password);
}
/**
* Submit a CAPTCHA already hosted on an existing website.
*
* @param url
* The URL of the CAPTCHA image.
* @return The decoded CAPTCHA.
* @throws Any
* exceptions sent by the server.
*/
public ResolvedCaptcha submit(URL url) throws CaptchaTraderException,
IOException {
final URI requestUri = apiURL.resolve("submit");
final HttpPost request = new HttpPost(requestUri);
final MultipartEntity entity = new MultipartEntity();
entity.addPart("api_key", new StringBody(applicationKey));
entity.addPart("username", new StringBody(username));
entity.addPart("password", new StringBody(password));
entity.addPart("value", new StringBody(url.toString()));
request.setEntity(entity);
final List<Object> response = validate(execute(request));
return new ResolvedCaptcha(this, ((Long) response.get(0)).intValue(),
(String) response.get(1));
}
/**
* Responds if an CAPTCHA wes correctly answered or not
*
* @param captcha
* the CAPTCHA object
* @param state
* <code>true</code> if the CAPTCHA was correctly resolved
* @throws CaptchaTraderException
* any of the possible errors
*/
public void response(ResolvedCaptcha captcha, boolean state)
throws CaptchaTraderException, IOException {
final URI requestUri = apiURL.resolve("respond");
final HttpPost request = new HttpPost(requestUri);
final MultipartEntity entity = new MultipartEntity();
entity.addPart("is_correct", new StringBody(state ? "1" : "0"));
entity.addPart("username", new StringBody(username));
entity.addPart("password", new StringBody(password));
entity.addPart("ticket",
new StringBody(Integer.toString(captcha.getID())));
request.setEntity(entity);
validate(execute(request));
}
/**
* Checks the amount of resolutions available on a users account
*
* @return The decoded CAPTCHA.
* @throws Any
* exceptions sent by the server.
*/
public int getCredits() throws CaptchaTraderException, IOException {
return ((Number) validate(
execute(new HttpGet(apiURL.resolve("get_credits/username:"
+ username + "/password:" + password + "/")))).get(1))
.intValue();
}
private List<Object> validate(List<Object> response)
throws CaptchaTraderException {
if ((long) response.get(0) == -1) {
throw translateException((String) response.get(1));
}
return response;
}
@SuppressWarnings("unchecked")
private List<Object> execute(HttpUriRequest request) throws IOException {
final HttpResponse response = client.execute(request);
try {
return (List<Object>) json.parse(new InputStreamReader(response
.getEntity().getContent()));
} catch (IllegalStateException | ParseException e) {
throw new IOException(e);
}
}
private CaptchaTraderException translateException(String error) {
switch (error) {
case "API KEY DISABLED":
return new ApplicationKeyDisabledException();
case " CONNECTION LIMIT":
return new ConnectionLimitException();
case "DAILY LIMIT":
return new DailyLimitException();
case "IMAGE TOO LARGE":
return new ImageTooLargeException();
case "INSUFFICIENT CREDITS":
return new InsuficientCreditsException();
case "INTERNAL ERROR":
return new InternalErrorException();
case "INVALID API KEY":
return new InvalidApplicationKeyException();
case "INVALID PARAMETERS":
return new InvalidParametersException();
case "INVALID URL":
return new InvalidURLException();
case "INVALID USER":
return new InvalidUserException();
case "USER NOT VALIDATED":
return new UserNotValidatedException();
case "NOT AN IMAGE":
return new NotAnImageException();
case "SUBMISSION ERROR":
return new SubmissionErrorException();
case "INCORRECT REPORTS":
return new IncorrectRespondsException();
case "INVALID TICKET":
return new InvalidTicketException();
default:
return new CaptchaTraderException(error);
}
}
}

View File

@@ -0,0 +1,40 @@
/**
*
*/
package com.captchatrader;
import java.io.IOException;
import com.captchatrader.exception.CaptchaTraderException;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ResolvedCaptcha {
private final CaptchaTrader api;
private final int id;
private final String answer;
public ResolvedCaptcha(CaptchaTrader api, int id, String answer) {
this.api = api;
this.id = id;
this.answer = answer;
}
public int getID() {
return id;
}
public String getAnswer() {
return answer;
}
public void valid() throws CaptchaTraderException, IOException {
api.response(this, true);
}
public void invalid() throws CaptchaTraderException, IOException {
api.response(this, true);
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ApplicationKeyDisabledException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public ApplicationKeyDisabledException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public ApplicationKeyDisabledException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public ApplicationKeyDisabledException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public ApplicationKeyDisabledException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public ApplicationKeyDisabledException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class CaptchaTraderException extends Exception {
private static final long serialVersionUID = 1L;
/**
*
*/
public CaptchaTraderException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public CaptchaTraderException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public CaptchaTraderException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public CaptchaTraderException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public CaptchaTraderException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ConnectionLimitException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public ConnectionLimitException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public ConnectionLimitException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public ConnectionLimitException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public ConnectionLimitException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public ConnectionLimitException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class DailyLimitException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public DailyLimitException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public DailyLimitException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public DailyLimitException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public DailyLimitException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public DailyLimitException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ImageTooLargeException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public ImageTooLargeException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public ImageTooLargeException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public ImageTooLargeException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public ImageTooLargeException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public ImageTooLargeException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class IncorrectRespondsException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public IncorrectRespondsException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public IncorrectRespondsException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public IncorrectRespondsException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public IncorrectRespondsException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public IncorrectRespondsException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class InsuficientCreditsException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public InsuficientCreditsException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public InsuficientCreditsException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public InsuficientCreditsException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public InsuficientCreditsException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public InsuficientCreditsException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class InternalErrorException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public InternalErrorException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public InternalErrorException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public InternalErrorException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public InternalErrorException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public InternalErrorException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class InvalidApplicationKeyException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public InvalidApplicationKeyException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public InvalidApplicationKeyException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public InvalidApplicationKeyException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public InvalidApplicationKeyException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public InvalidApplicationKeyException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class InvalidParametersException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public InvalidParametersException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public InvalidParametersException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public InvalidParametersException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public InvalidParametersException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public InvalidParametersException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class InvalidTicketException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public InvalidTicketException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public InvalidTicketException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public InvalidTicketException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public InvalidTicketException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public InvalidTicketException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class InvalidURLException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public InvalidURLException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public InvalidURLException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public InvalidURLException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public InvalidURLException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public InvalidURLException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class InvalidUserException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public InvalidUserException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public InvalidUserException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public InvalidUserException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public InvalidUserException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public InvalidUserException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class NotAnImageException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public NotAnImageException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public NotAnImageException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public NotAnImageException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public NotAnImageException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public NotAnImageException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class SubmissionErrorException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public SubmissionErrorException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public SubmissionErrorException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public SubmissionErrorException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public SubmissionErrorException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public SubmissionErrorException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,57 @@
/**
*
*/
package com.captchatrader.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class UserNotValidatedException extends CaptchaTraderException {
private static final long serialVersionUID = 1L;
/**
*
*/
public UserNotValidatedException() {
// TODO Auto-generated constructor stub
}
/**
* @param message
*/
public UserNotValidatedException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
/**
* @param cause
*/
public UserNotValidatedException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
*/
public UserNotValidatedException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
/**
* @param message
* @param cause
* @param enableSuppression
* @param writableStackTrace
*/
public UserNotValidatedException(String message, Throwable cause,
boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// TODO Auto-generated constructor stub
}
}

View File

@@ -0,0 +1,117 @@
/**
*
*/
package com.rogiel.httpchannel.captcha.impl;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.captchatrader.CaptchaTrader;
import com.captchatrader.ResolvedCaptcha;
import com.captchatrader.exception.CaptchaTraderException;
import com.rogiel.httpchannel.captcha.ImageCaptcha;
import com.rogiel.httpchannel.captcha.ImageCaptchaService;
import com.rogiel.httpchannel.captcha.exception.AuthenticationCaptchaServiceException;
import com.rogiel.httpchannel.captcha.exception.InvalidCaptchaServiceException;
import com.rogiel.httpchannel.captcha.exception.UnsolvableCaptchaServiceException;
/**
* Implements CAPTCHA solving using CaptchaTrader.com service. If
* username-password authentication is not desired, send the API key as username
* and <code>null</code> password.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class CaptchaTraderService implements ImageCaptchaService {
private static final Logger logger = LoggerFactory
.getLogger(CaptchaTraderService.class);
private static final String APP_KEY = "2acc44805ec208cc4d6b00c75a414996";
/**
* The current application key to be used
*/
private String currentApplicationKey = APP_KEY;
/**
* The CaptchaTrader.com API object
*/
private CaptchaTrader api;
@Override
public int authenticate(String username, String password)
throws AuthenticationCaptchaServiceException {
api = new CaptchaTrader(currentApplicationKey, username, password);
logger.debug("Authenticating into CaptchaTrader");
try {
// this will validate the account
return (int) Math.ceil(((double) api.getCredits()) / 10);
} catch (IOException | CaptchaTraderException e) {
throw new AuthenticationCaptchaServiceException(e);
}
}
@Override
public void solve(ImageCaptcha captcha)
throws UnsolvableCaptchaServiceException {
try {
logger.debug("Resolving CAPTCHA {}", captcha.getImageURL());
final ResolvedCaptcha resolved = api.submit(captcha.getImageURL());
captcha.setAnswer(resolved.getAnswer());
captcha.setAttachment(resolved);
logger.debug("CAPTCHA solved, answer is \"{}\"",
resolved.getAnswer());
} catch (IOException | CaptchaTraderException e) {
throw new UnsolvableCaptchaServiceException(e);
}
}
@Override
public void valid(ImageCaptcha captcha)
throws InvalidCaptchaServiceException {
final Object attachment = captcha.getAttachment();
if (attachment instanceof ResolvedCaptcha) {
try {
logger.debug("Notifying server that CAPTCHA {} is valid",
captcha);
((ResolvedCaptcha) attachment).valid();
} catch (CaptchaTraderException | IOException e) {
throw new InvalidCaptchaServiceException(e);
}
} else {
throw new InvalidCaptchaServiceException();
}
}
@Override
public void invalid(ImageCaptcha captcha)
throws InvalidCaptchaServiceException {
final Object attachment = captcha.getAttachment();
if (attachment instanceof ResolvedCaptcha) {
try {
logger.debug("Notifying server that CAPTCHA {} is invalid",
captcha);
((ResolvedCaptcha) attachment).invalid();
} catch (CaptchaTraderException | IOException e) {
throw new InvalidCaptchaServiceException(e);
}
} else {
throw new InvalidCaptchaServiceException();
}
}
/**
* Sets the CaptchaTrader API key. Each application should provide a key,
* otherwise the default "HttpChannel" key will be used.
*
* @param key
* the application key
*/
public void setApplicationKey(String key) {
if (key == null)
key = APP_KEY;
logger.debug("Setting new application key as {}", key);
currentApplicationKey = key;
}
}

View File

@@ -0,0 +1,42 @@
/**
*
*/
package com.captchatrader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Properties;
import org.junit.Test;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class CaptchaTraderTest {
/**
* Test method for
* {@link com.captchatrader.old.CaptchaTrader#respond(boolean)}.
*
* @throws Exception
*/
@Test
public void testRespond() throws Exception {
final Properties p = new Properties();
p.load(Files.newInputStream(
Paths.get("../../httpchannel-captcha/src/test/resources/captchatrader.properties"),
StandardOpenOption.READ));
final CaptchaTrader api = new CaptchaTrader(
"2acc44805ec208cc4d6b00c75a414996", p.getProperty("username"),
p.getProperty("password"));
final ResolvedCaptcha resolved = api
.submit(new URL(
"http://www.google.com/recaptcha/api/image?c=03AHJ_VusNSxAzZgs9OEvH79rOWOFDYXE2ElE5qkCr9kFU-ZU7gqy72tqEL3j_qCLYwdXgh4jaxU1iECISuUwt0zHbelni-lq8c7RVGSjUtJiMyHwlTTsG5CxWKIEus--yy3GPvwaW9l4N7hFnT57lLq272EOxcFDGYA"));
System.out.println(resolved);
resolved.valid();
}
}

View File

@@ -1,24 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>httpchannel-capcha</artifactId>
<groupId>com.rogiel.httpchannel</groupId>
<version>1.0.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>httpchannel-captcha-recaptcha</artifactId>
<name>HttpChannel/CaptchaService/ReCaptcha</name>
<description>This module provides captcha resolving for Google ReCaptcha</description>
<dependencies>
<dependency>
<groupId>com.rogiel.httpchannel</groupId>
<artifactId>httpchannel-api</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.rogiel.httpchannel</groupId>
<artifactId>httpchannel-util</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -1,36 +0,0 @@
/**
*
*/
package com.rogiel.httpchannel.captcha.impl;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.regex.Pattern;
import com.rogiel.httpchannel.util.PatternUtils;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class AjaxReCaptchaService extends BaseReCaptchaService {
private static final Pattern CAPTCHA_URL_PATTERN = Pattern
.compile("Recaptcha\\.create\\(\"([0-9A-z|_|\\-]*)\", ");
private static final String BASE_URL = "http://www.google.com/recaptcha/api/challenge?ajax=1&k=";
@Override
public ReCaptcha create(String content) throws MalformedURLException {
final String siteID = PatternUtils
.find(CAPTCHA_URL_PATTERN, content, 1);
try {
return super.create(get(BASE_URL + siteID).asString());
} catch (IOException e) {
return null;
}
}
@Override
public boolean resolve(ReCaptcha captcha) {
// not supported!
return false;
}
}

View File

@@ -1,34 +0,0 @@
/**
*
*/
package com.rogiel.httpchannel.captcha.impl;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Pattern;
import com.rogiel.httpchannel.captcha.AbstractImageCaptchaService;
import com.rogiel.httpchannel.util.PatternUtils;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class BaseReCaptchaService extends
AbstractImageCaptchaService<ReCaptcha> {
private static final Pattern CAPTCHA_IMAGE_PATTERN = Pattern
.compile("challenge : '(.*)'");
private static final String BASE_URL = "http://www.google.com/recaptcha/api/image?c=";
@Override
public ReCaptcha create(String content) throws MalformedURLException {
final String id = PatternUtils.find(CAPTCHA_IMAGE_PATTERN, content, 1);
return new ReCaptcha(new URL(BASE_URL + id), id);
}
@Override
public boolean resolve(ReCaptcha captcha) {
// not supported!
return false;
}
}

View File

@@ -1,41 +0,0 @@
/**
*
*/
package com.rogiel.httpchannel.captcha.impl;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.regex.Pattern;
import com.rogiel.httpchannel.util.htmlparser.HTMLPage;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class EmbeddedReCaptchaService extends BaseReCaptchaService {
private static final Pattern CAPTCHA_URL_PATTERN = Pattern
.compile("http://www\\.google\\.com/recaptcha/api/challenge\\?k=([0-9A-z|\\-]*)(&(.*))?");
@Override
public ReCaptcha create(String content) throws MalformedURLException {
try {
return create(HTMLPage.parse(content));
} catch (IOException e) {
return null;
}
}
public ReCaptcha create(HTMLPage page) throws IOException {
final String url = page.findScriptSrc(CAPTCHA_URL_PATTERN);
if (url == null)
return null;
return super.create(get(url).asString());
}
@Override
public boolean resolve(ReCaptcha captcha) {
// not supported!
return false;
}
}

View File

@@ -1,15 +0,0 @@
package com.rogiel.httpchannel.captcha.impl;
import java.net.URL;
import com.rogiel.httpchannel.captcha.AbstractImageCaptcha;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ReCaptcha extends AbstractImageCaptcha {
public ReCaptcha(URL url, String ID) {
super(url, ID);
}
}

View File

@@ -1,25 +0,0 @@
/**
*
*/
package com.rogiel.httpchannel.captcha.impl;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class AjaxReCaptchaServiceTest {
@Test
public void test() throws MalformedURLException, IOException {
final String content = IOUtils.toString(new URL(
"http://www.uploadking.com/WM3PHD9JAY").openStream());
final AjaxReCaptchaService ajax = new AjaxReCaptchaService();
ajax.create(content);
}
}

View File

@@ -14,6 +14,13 @@
<description>This module provides implementations for captcha resolving</description>
<modules>
<module>httpchannel-captcha-recaptcha</module>
<module>httpchannel-captcha-captchatrader</module>
</modules>
<dependencies>
<dependency>
<groupId>com.rogiel.httpchannel</groupId>
<artifactId>httpchannel-api</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1 @@
/captchatrader.properties

View File

@@ -10,11 +10,4 @@
<groupId>com.rogiel.httpchannel.services</groupId>
<name>HttpChannel/Service/DepositFiles</name>
<description>Provides upload access to depositfiles.com</description>
<dependencies>
<dependency>
<groupId>com.rogiel.httpchannel</groupId>
<artifactId>httpchannel-captcha-recaptcha</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -5,8 +5,9 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.regex.Pattern;
import com.rogiel.httpchannel.captcha.impl.EmbeddedReCaptchaService;
import com.rogiel.httpchannel.captcha.impl.ReCaptcha;
import com.rogiel.httpchannel.captcha.ImageCaptcha;
import com.rogiel.httpchannel.captcha.ReCaptchaExtractor;
import com.rogiel.httpchannel.captcha.exception.UnsolvableCaptchaServiceException;
import com.rogiel.httpchannel.service.AbstractAuthenticator;
import com.rogiel.httpchannel.service.AbstractHttpService;
import com.rogiel.httpchannel.service.AbstractUploader;
@@ -50,8 +51,6 @@ public class DepositFilesService extends AbstractHttpService implements
private static final Pattern VALID_LOGIN_REDIRECT = Pattern
.compile("window.location.href");
private final EmbeddedReCaptchaService captchaService = new EmbeddedReCaptchaService();
@Override
public ServiceID getID() {
return SERVICE_ID;
@@ -137,12 +136,15 @@ public class DepositFilesService extends AbstractHttpService implements
@Override
public UploadChannel openChannel() throws IOException {
logger.debug("Starting upload to depositfiles.com");
final HTMLPage page = get("http://www.depositfiles.com/").asPage();
final String url = page.findFormAction(UPLOAD_URL_PATTERN);
final String uploadID = page.getInputValue("UPLOAD_IDENTIFIER");
final String maxFileSize = page.getInputValue("MAX_FILE_SIZE");
logger.debug("Upload URL: {}, ID: {}", url, uploadID);
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(url).parameter("files", channel)
.parameter("go", true)
@@ -178,13 +180,16 @@ public class DepositFilesService extends AbstractHttpService implements
@Override
public void login() throws IOException {
logger.debug("Authenticating into depositfiles.com");
HTMLPage page = post("http://depositfiles.com/login.php?return=%2F")
.parameter("go", true)
.parameter("login", credential.getUsername())
.parameter("password", credential.getPassword()).asPage();
final ReCaptcha captcha = captchaService.create(page);
final ImageCaptcha captcha = ReCaptchaExtractor.extractCaptcha(
page, http);
if (captcha != null) {
logger.debug("Service is requiring CAPTCHA {}", captcha);
resolveCaptcha(captcha);
page = post("http://depositfiles.com/login.php?return=%2F")
.parameter("go", true)
@@ -195,9 +200,17 @@ public class DepositFilesService extends AbstractHttpService implements
captcha.getAnswer()).asPage();
}
if (!page.contains(VALID_LOGIN_REDIRECT))
throw new AuthenticationInvalidCredentialException();
return;
final ImageCaptcha testCaptcha = ReCaptchaExtractor.extractCaptcha(
page, http);
if (testCaptcha != null) {
captchaService.invalid(captcha);
throw new UnsolvableCaptchaServiceException();
} else {
captchaService.valid(captcha);
if (!page.contains(VALID_LOGIN_REDIRECT))
throw new AuthenticationInvalidCredentialException();
return;
}
}
@Override

View File

@@ -0,0 +1,13 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>httpchannel-service</artifactId>
<groupId>com.rogiel.httpchannel</groupId>
<version>1.0.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>httpchannel-service-filesonic</artifactId>
<groupId>com.rogiel.httpchannel.services</groupId>
<name>HttpChannel/Service/FileSonic</name>
<description>Provides download and upload access to filesonic.com</description>
</project>

View File

@@ -0,0 +1,56 @@
/**
*
*/
package com.rogiel.httpchannel.filesonic;
import java.io.IOException;
import java.net.URL;
import javax.xml.bind.JAXB;
import com.rogiel.httpchannel.filesonic.xml.FSAPI;
import com.rogiel.httpchannel.filesonic.xml.FSGetUploadURL;
import com.rogiel.httpchannel.filesonic.xml.FSUpload;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class FileSonicAPI {
private static final String BASE_URL = "http://api.filesonic.com/";
private String email;
private String password;
public Object getInfo(int id) {
return id;
}
public URL getUploadURL() throws IOException {
return new URL(((FSGetUploadURL) execute(FSUpload.class,
"upload?method=getUploadUrl").getResponse()).getResponse()
.getUploadURL());
}
public long getMaxFilesize() throws IOException {
return ((FSGetUploadURL) execute(FSUpload.class,
"upload?method=getUploadUrl").getResponse()).getResponse()
.getMaxFilesize();
}
public void login(String email, String password) {
this.email = email;
this.password = password;
}
public void logout() {
this.email = null;
this.password = null;
}
private <T extends FSAPI> T execute(Class<T> type, String requestURL)
throws IOException {
final URL url = new URL(BASE_URL + requestURL + "&u=" + email + "&p="
+ password + "&format=xml");
return JAXB.unmarshal(url.openStream(), type);
}
}

View File

@@ -0,0 +1,12 @@
/**
*
*/
package com.rogiel.httpchannel.filesonic.xml;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class FSAPI {
}

View File

@@ -0,0 +1,40 @@
/**
*
*/
package com.rogiel.httpchannel.filesonic.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
@XmlRootElement(name = "getUploadUrl")
@XmlAccessorType(XmlAccessType.NONE)
public class FSGetUploadURL extends FSResponse {
@XmlElement(name = "response")
private FSGetUploadURLResponse response;
@XmlAccessorType(XmlAccessType.NONE)
public static class FSGetUploadURLResponse {
@XmlElement(name = "url")
private String uploadURL;
@XmlElement(name = "max-filesize")
private long maxFilesize;
public String getUploadURL() {
return uploadURL;
}
public long getMaxFilesize() {
return maxFilesize;
}
}
public FSGetUploadURLResponse getResponse() {
return response;
}
}

View File

@@ -0,0 +1,21 @@
/**
*
*/
package com.rogiel.httpchannel.filesonic.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
@XmlAccessorType(XmlAccessType.NONE)
public abstract class FSResponse {
@XmlElement(name = "status")
private String status;
public String getStatus() {
return status;
}
}

View File

@@ -0,0 +1,25 @@
/**
*
*/
package com.rogiel.httpchannel.filesonic.xml;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "FSApi_Upload")
public class FSUpload extends FSAPI {
@XmlElements(value = { @XmlElement(name = "getUploadUrl", type = FSGetUploadURL.class) })
private FSResponse response;
public FSResponse getResponse() {
return response;
}
}

View File

@@ -0,0 +1,206 @@
/*
* This file is part of seedbox <github.com/seedbox>.
*
* seedbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* seedbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with seedbox. If not, see <http://www.gnu.org/licenses/>.
*/
package com.rogiel.httpchannel.service.impl;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.regex.Pattern;
import com.rogiel.httpchannel.filesonic.FileSonicAPI;
import com.rogiel.httpchannel.service.AbstractAuthenticator;
import com.rogiel.httpchannel.service.AbstractHttpService;
import com.rogiel.httpchannel.service.AbstractUploader;
import com.rogiel.httpchannel.service.AuthenticationService;
import com.rogiel.httpchannel.service.Authenticator;
import com.rogiel.httpchannel.service.AuthenticatorCapability;
import com.rogiel.httpchannel.service.CapabilityMatrix;
import com.rogiel.httpchannel.service.Credential;
import com.rogiel.httpchannel.service.Service;
import com.rogiel.httpchannel.service.ServiceID;
import com.rogiel.httpchannel.service.UploadChannel;
import com.rogiel.httpchannel.service.UploadService;
import com.rogiel.httpchannel.service.Uploader;
import com.rogiel.httpchannel.service.UploaderCapability;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannel;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannel.LinkedUploadChannelCloseCallback;
import com.rogiel.httpchannel.service.config.NullAuthenticatorConfiguration;
import com.rogiel.httpchannel.service.config.NullUploaderConfiguration;
import com.rogiel.httpchannel.util.PatternUtils;
/**
* This service handles login, upload and download to MegaUpload.com.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
* @since 1.0
*/
public class FileSonicService extends AbstractHttpService implements Service,
UploadService<NullUploaderConfiguration>,
AuthenticationService<NullAuthenticatorConfiguration> {
/**
* This service ID
*/
public static final ServiceID SERVICE_ID = ServiceID.create("megaupload");
/**
* The download URL pattern
*/
private static final Pattern DOWNLOAD_URL_PATTERN = Pattern
.compile("http://www.filesonic.com/file/[0-9A-z]*");
/**
* The FileSonic API
*/
private final FileSonicAPI api = new FileSonicAPI();
@Override
public ServiceID getID() {
return SERVICE_ID;
}
@Override
public int getMajorVersion() {
return 1;
}
@Override
public int getMinorVersion() {
return 0;
}
@Override
public Uploader<NullUploaderConfiguration> getUploader(String filename,
long filesize, NullUploaderConfiguration configuration) {
return new UploaderImpl(filename, filesize, configuration);
}
@Override
public Uploader<NullUploaderConfiguration> getUploader(String filename,
long filesize) {
return getUploader(filename, filesize, newUploaderConfiguration());
}
@Override
public NullUploaderConfiguration newUploaderConfiguration() {
return NullUploaderConfiguration.SHARED_INSTANCE;
}
@Override
public long getMaximumFilesize() {
try {
return api.getMaxFilesize();
} catch (IOException e) {
return -1;
}
}
@Override
public String[] getSupportedExtensions() {
return null;
}
@Override
public CapabilityMatrix<UploaderCapability> getUploadCapabilities() {
return new CapabilityMatrix<UploaderCapability>(
UploaderCapability.NON_PREMIUM_ACCOUNT_UPLOAD,
UploaderCapability.PREMIUM_ACCOUNT_UPLOAD);
}
@Override
public Authenticator<NullAuthenticatorConfiguration> getAuthenticator(
Credential credential, NullAuthenticatorConfiguration configuration) {
return new AuthenticatorImpl(credential, configuration);
}
@Override
public Authenticator<NullAuthenticatorConfiguration> getAuthenticator(
Credential credential) {
return getAuthenticator(credential, newAuthenticatorConfiguration());
}
@Override
public NullAuthenticatorConfiguration newAuthenticatorConfiguration() {
return NullAuthenticatorConfiguration.SHARED_INSTANCE;
}
@Override
public CapabilityMatrix<AuthenticatorCapability> getAuthenticationCapability() {
return new CapabilityMatrix<AuthenticatorCapability>();
}
protected class UploaderImpl extends
AbstractUploader<NullUploaderConfiguration> implements
Uploader<NullUploaderConfiguration>,
LinkedUploadChannelCloseCallback {
private Future<String> uploadFuture;
public UploaderImpl(String filename, long filesize,
NullUploaderConfiguration configuration) {
super(filename, filesize, configuration);
}
@Override
public UploadChannel openChannel() throws IOException {
logger.debug("Starting upload to filesonic.com");
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(api.getUploadURL().toString())
.parameter("files[]", channel).asStringAsync();
return waitChannelLink(channel, uploadFuture);
}
@Override
public String finish() throws IOException {
try {
return PatternUtils.find(DOWNLOAD_URL_PATTERN,
uploadFuture.get());
} catch (InterruptedException e) {
return null;
} catch (ExecutionException e) {
throw (IOException) e.getCause();
}
}
}
protected class AuthenticatorImpl extends
AbstractAuthenticator<NullAuthenticatorConfiguration> implements
Authenticator<NullAuthenticatorConfiguration> {
public AuthenticatorImpl(Credential credential,
NullAuthenticatorConfiguration configuration) {
super(credential, configuration);
}
@Override
public void login() throws IOException {
logger.debug("Logging to filesonic.com");
api.login(credential.getUsername(), credential.getPassword());
// if (username == null)
// throw new AuthenticationInvalidCredentialException();
}
@Override
public void logout() throws IOException {
post("http://www.megaupload.com/?c=account").parameter("logout",
true).request();
// TODO check logout status
}
}
@Override
public String toString() {
return this.getClass().getSimpleName() + " " + getMajorVersion() + "."
+ getMinorVersion();
}
}

View File

@@ -0,0 +1 @@
com.rogiel.httpchannel.service.impl.FileSonicService

View File

@@ -196,9 +196,12 @@ public class HotFileService extends AbstractHttpService implements Service,
@Override
public UploadChannel openChannel() throws IOException {
logger.debug("Starting upload to hotfile.com");
final HTMLPage page = get("http://www.hotfile.com/").asPage();
final String action = page.findFormAction(UPLOAD_URL_PATTERN);
logger.debug("Upload URL is {}", action);
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(action)
@@ -227,6 +230,7 @@ public class HotFileService extends AbstractHttpService implements Service,
@Override
public DownloadChannel openChannel(DownloadListener listener,
long position) throws IOException {
logger.debug("Downloading {} from hotfile.com", url);
final HTMLPage page = get(url).asPage();
// // try to find timer
@@ -243,6 +247,7 @@ public class HotFileService extends AbstractHttpService implements Service,
final String downloadUrl = page
.findLink(DOWNLOAD_DIRECT_LINK_PATTERN);
logger.debug("Download link is {}", downloadUrl);
// final String tmHash = PatternUtils.find(DOWNLOAD_TMHASH_PATTERN,
// content);F
if (downloadUrl != null && downloadUrl.length() > 0) {
@@ -254,49 +259,6 @@ public class HotFileService extends AbstractHttpService implements Service,
return new InputStreamDownloadChannel(downloadResponse
.getEntity().getContent(), contentLength, filename);
// } else if (tmHash != null) {
// String dlUrl = PatternUtils.find(FREE_DOWNLOAD_URL_PATTERN,
// content);
//
// String action = PatternUtils.find(DOWNLOAD_ACTION_PATTERN,
// content, 1);
// int tm = PatternUtils.findInt(DOWNLOAD_TM_PATTERN, content,
// 1);
// int wait = PatternUtils.findInt(DOWNLOAD_WAIT_PATTERN,
// content,
// 1);
// String waitHash =
// PatternUtils.find(DOWNLOAD_WAITHASH_PATTERN,
// content, 1);
// String upId = PatternUtils.find(DOWNLOAD_UPIDHASH_PATTERN,
// content, 1);
//
// System.out.println("Wait time: "+wait);
//
// if (wait > 0)
// timer(listener, wait * 1000);
//
// final HttpPost downloadPost = new
// HttpPost("http://www.hotfile.com"+dlUrl);
// final List<NameValuePair> pairs = new
// ArrayList<NameValuePair>();
// pairs.add(new BasicNameValuePair("action", action));
// pairs.add(new BasicNameValuePair("tm",
// Integer.toString(tm)));
// pairs.add(new BasicNameValuePair("tmhash", tmHash));
// pairs.add(new BasicNameValuePair("wait",
// Integer.toString(wait)));
// pairs.add(new BasicNameValuePair("waithash", waitHash));
// pairs.add(new BasicNameValuePair("upidhash", upId));
//
// downloadPost.setEntity(new UrlEncodedFormEntity(pairs));
//
// final HttpResponse downloadResponse = client
// .execute(downloadPost);
// System.out.println(IOUtils.toString(downloadResponse.getEntity().getContent()));
//
// return new InputStreamDownloadChannel(downloadResponse
// .getEntity().getContent(), 0, "haha");
} else {
throw new IOException("Download link not found");
}
@@ -313,6 +275,7 @@ public class HotFileService extends AbstractHttpService implements Service,
@Override
public void login() throws ClientProtocolException, IOException {
logger.debug("Authenticating hotfile.com");
HTMLPage page = post("http://www.hotfile.com/login.php")
.parameter("returnto", "/index.php")
.parameter("user", credential.getUsername())

View File

@@ -205,10 +205,12 @@ public class MegaUploadService extends AbstractHttpService implements Service,
@Override
public UploadChannel openChannel() throws IOException {
logger.debug("Starting upload to megaupload.com");
final HTMLPage page = get("http://www.megaupload.com/multiupload/")
.asPage();
final String url = page.findFormAction(UPLOAD_URL_PATTERN);
logger.debug("Upload URL is {}", url);
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(url)
.parameter("multimessage_0", configuration.description())
@@ -240,11 +242,13 @@ public class MegaUploadService extends AbstractHttpService implements Service,
@Override
public DownloadChannel openChannel(DownloadListener listener,
long position) throws IOException {
logger.debug("Starting {} download from megaupload.com", url);
HttpResponse response = get(url).request();
// disable direct downloads, we don't support them!
if (response.getEntity().getContentType().getValue()
.equals("application/octet-stream")) {
logger.debug("Direct download is enabled, deactivating");
// close connection
response.getEntity().getContent().close();
@@ -263,6 +267,7 @@ public class MegaUploadService extends AbstractHttpService implements Service,
// try to find timer
int timer = page.findScriptAsInt(DOWNLOAD_TIMER, 1);
if (timer > 0 && configuration.getRespectWaitTime()) {
logger.debug("");
timer(listener, timer * 1000);
}
final String downloadUrl = page
@@ -299,6 +304,7 @@ public class MegaUploadService extends AbstractHttpService implements Service,
@Override
public void login() throws IOException {
logger.debug("Starting login to megaupload.com");
final HTMLPage page = post("http://www.megaupload.com/?c=login")
.parameter("login", true)
.parameter("username", credential.getUsername())

View File

@@ -183,8 +183,10 @@ public class MultiUploadService extends AbstractHttpService implements Service,
@Override
public UploadChannel openChannel() throws IOException {
logger.debug("Starting upload to multiupload.com");
final String url = get("http://www.multiupload.com/").asPage()
.findFormAction(UPLOAD_URL_PATTERN);
logger.debug("Upload URL is {}", url);
final LinkedUploadChannel channel = createLinkedChannel(this);
PostMultipartRequest request = multipartPost(url).parameter(
@@ -192,6 +194,7 @@ public class MultiUploadService extends AbstractHttpService implements Service,
"file_0", channel);
for (final MultiUploadMirrorService mirror : configuration
.uploadServices()) {
logger.debug("Adding {} as mirror", mirror.name());
request.parameter("service_" + mirror.id, 1);
}
@@ -204,6 +207,7 @@ public class MultiUploadService extends AbstractHttpService implements Service,
try {
final String linkId = PatternUtils.find(DOWNLOAD_ID_PATTERN,
uploadFuture.get(), 1);
logger.debug("Upload to multiupload.com finished");
if (linkId == null)
return null;
return new StringBuilder("http://www.multiupload.com/").append(
@@ -231,6 +235,7 @@ public class MultiUploadService extends AbstractHttpService implements Service,
DownloadNotAuthorizedException, DownloadNotResumableException {
final HTMLPage page = get(url).asPage();
final String link = page.findLink(DIRECT_DOWNLOAD_LINK_PATTERN);
logger.debug("Direct download link is {}", link);
if (link == null)
throw new DownloadLinkNotFoundException();
return download(get(link).position(position));

View File

@@ -10,11 +10,4 @@
<groupId>com.rogiel.httpchannel.services</groupId>
<name>HttpChannel/Service/UploadHere</name>
<description>Provides upload access to uploadhere.com</description>
<dependencies>
<dependency>
<groupId>com.rogiel.httpchannel</groupId>
<artifactId>httpchannel-captcha-recaptcha</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>

View File

@@ -6,8 +6,8 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.regex.Pattern;
import com.rogiel.httpchannel.captcha.impl.AjaxReCaptchaService;
import com.rogiel.httpchannel.captcha.impl.ReCaptcha;
import com.rogiel.httpchannel.captcha.ImageCaptcha;
import com.rogiel.httpchannel.captcha.ReCaptchaExtractor;
import com.rogiel.httpchannel.service.AbstractAuthenticator;
import com.rogiel.httpchannel.service.AbstractHttpDownloader;
import com.rogiel.httpchannel.service.AbstractHttpService;
@@ -67,8 +67,6 @@ public class UploadHereService extends AbstractHttpService implements Service,
private static final String INVALID_LOGIN_STRING = "Incorrect username and/or password. Please try again!";
private final AjaxReCaptchaService captchaService = new AjaxReCaptchaService();
@Override
public ServiceID getID() {
return SERVICE_ID;
@@ -190,6 +188,9 @@ public class UploadHereService extends AbstractHttpService implements Service,
final String url = page.findFormAction(UPLOAD_URL_PATTERN);
final String uploadID = page.getInputValue("UPLOAD_IDENTIFIER");
logger.debug("Upload URL: {}, UserCookie: {}, UploadID: {}",
new Object[] { url, userCookie, uploadID });
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(url).parameter("file_0", channel)
.parameter("u", userCookie)
@@ -202,6 +203,7 @@ public class UploadHereService extends AbstractHttpService implements Service,
try {
final String linkId = PatternUtils.find(DOWNLOAD_ID_PATTERN,
uploadFuture.get(), 1);
logger.debug("Upload to uploadhere.com finished");
if (linkId == null)
return null;
return new StringBuilder("http://www.uploadhere.com/").append(
@@ -230,15 +232,24 @@ public class UploadHereService extends AbstractHttpService implements Service,
HTMLPage page = get(url).asPage();
final int waitTime = page.findScriptAsInt(TIMER_PATTERN, 1) * 1000;
logger.debug("Wait time is {}", waitTime);
final ReCaptcha captcha = captchaService.create(page.toString());
final ImageCaptcha captcha = ReCaptchaExtractor.extractAjaxCaptcha(
page, http);
if (captcha != null) {
logger.debug("Service is requiring CAPTCHA {}", captcha);
final long start = System.currentTimeMillis();
resolveCaptcha(captcha);
final long delta = System.currentTimeMillis() - start;
if (delta < waitTime)
if (delta < waitTime) {
logger.debug(
"After captcha resolving, still {} ms remaining",
delta);
timer(listener, waitTime - delta);
} else {
logger.debug("CAPTCHA solving took longer than timer, skipping it");
}
String content = post(url)
.parameter("recaptcha_challenge_field", captcha.getID())
@@ -246,10 +257,15 @@ public class UploadHereService extends AbstractHttpService implements Service,
captcha.getAnswer()).asString();
String downloadLink = PatternUtils.find(
DIERCT_DOWNLOAD_URL_PATTERN, content, 1);
if (downloadLink == null)
if (downloadLink == null) {
captchaService.invalid(captcha);
throw new InvalidCaptchaException();
} else {
captchaService.valid(captcha);
}
downloadLink = downloadLink.replaceAll(Pattern.quote("\\/"),
"/");
logger.debug("Direct download URL is {}", downloadLink);
return download(get(downloadLink).position(position));
}
throw new DownloadLinkNotFoundException();

View File

@@ -1,20 +1,22 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>httpchannel-service</artifactId>
<groupId>com.rogiel.httpchannel</groupId>
<version>1.0.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>httpchannel-service-uploadking</artifactId>
<groupId>com.rogiel.httpchannel.services</groupId>
<name>HttpChannel/Service/UploadKing</name>
<description>Provides upload access to uploadking.com</description>
<dependencies>
<dependency>
<groupId>com.rogiel.httpchannel</groupId>
<artifactId>httpchannel-captcha-recaptcha</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>httpchannel-service</artifactId>
<groupId>com.rogiel.httpchannel</groupId>
<version>1.0.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>httpchannel-service-uploadking</artifactId>
<groupId>com.rogiel.httpchannel.services</groupId>
<name>HttpChannel/Service/UploadKing</name>
<description>Provides upload access to uploadking.com</description>
<dependencies>
<dependency>
<groupId>com.rogiel.httpchannel.captcha</groupId>
<artifactId>httpchannel-captcha-captchatrader</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -6,8 +6,8 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.regex.Pattern;
import com.rogiel.httpchannel.captcha.impl.AjaxReCaptchaService;
import com.rogiel.httpchannel.captcha.impl.ReCaptcha;
import com.rogiel.httpchannel.captcha.ImageCaptcha;
import com.rogiel.httpchannel.captcha.ReCaptchaExtractor;
import com.rogiel.httpchannel.service.AbstractAuthenticator;
import com.rogiel.httpchannel.service.AbstractHttpDownloader;
import com.rogiel.httpchannel.service.AbstractHttpService;
@@ -67,8 +67,6 @@ public class UploadKingService extends AbstractHttpService implements Service,
private static final String INVALID_LOGIN_STRING = "Incorrect username and/or password. Please try again!";
private final AjaxReCaptchaService captchaService = new AjaxReCaptchaService();
@Override
public ServiceID getID() {
return SERVICE_ID;
@@ -190,6 +188,9 @@ public class UploadKingService extends AbstractHttpService implements Service,
final String url = page.findFormAction(UPLOAD_URL_PATTERN);
final String uploadID = page.getInputValue("UPLOAD_IDENTIFIER");
logger.debug("Upload URL: {}, UserCookie: {}, UploadID: {}",
new Object[] { url, userCookie, uploadID });
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(url).parameter("file", channel)
.parameter("u", userCookie)
@@ -202,6 +203,7 @@ public class UploadKingService extends AbstractHttpService implements Service,
try {
final String linkId = PatternUtils.find(DOWNLOAD_ID_PATTERN,
uploadFuture.get(), 1);
logger.debug("Upload to uploadking.com finished");
if (linkId == null)
return null;
return new StringBuilder("http://www.uploadking.com/").append(
@@ -224,19 +226,29 @@ public class UploadKingService extends AbstractHttpService implements Service,
@Override
public DownloadChannel openChannel(DownloadListener listener,
long position) throws IOException {
logger.debug("Downloading {} with uploadking.com");
HTMLPage page = get(url).asPage();
final int waitTime = page.findScriptAsInt(TIMER_PATTERN, 1) * 1000;
logger.debug("Wait time is {}", waitTime);
final ReCaptcha captcha = captchaService.create(page.toString());
final ImageCaptcha captcha = ReCaptchaExtractor.extractAjaxCaptcha(
page, http);
if (captcha != null) {
logger.debug("Service is requiring CAPTCHA {}", captcha);
final long start = System.currentTimeMillis();
resolveCaptcha(captcha);
final long delta = System.currentTimeMillis() - start;
if (delta < waitTime)
if (delta < waitTime) {
logger.debug(
"After captcha resolving, still {} ms remaining",
delta);
timer(listener, waitTime - delta);
} else {
logger.debug("CAPTCHA solving took longer than timer, skipping it");
}
String content = post(url)
.parameter("recaptcha_challenge_field", captcha.getID())
@@ -244,10 +256,15 @@ public class UploadKingService extends AbstractHttpService implements Service,
captcha.getAnswer()).asString();
String downloadLink = PatternUtils.find(
DIERCT_DOWNLOAD_URL_PATTERN, content, 1);
if (downloadLink == null)
if (downloadLink == null) {
captchaService.invalid(captcha);
throw new InvalidCaptchaException();
} else {
captchaService.valid(captcha);
}
downloadLink = downloadLink.replaceAll(Pattern.quote("\\/"),
"/");
logger.debug("Direct download URL is {}", downloadLink);
return download(get(downloadLink).position(position));
}
throw new DownloadLinkNotFoundException();

View File

@@ -4,14 +4,20 @@ import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Properties;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import com.rogiel.httpchannel.captcha.CaptchaService;
import com.rogiel.httpchannel.captcha.impl.CaptchaTraderService;
import com.rogiel.httpchannel.service.DownloadChannel;
import com.rogiel.httpchannel.service.UploaderCapability;
import com.rogiel.httpchannel.util.ChannelUtils;
@@ -37,26 +43,19 @@ public class UploadKingServiceTest {
System.out.println(url);
}
// @Test
// public void testDownloader() throws IOException {
// service.setCaptchaResolver(new CaptchaResolver() {
// @Override
// public boolean resolve(Captcha rawCaptcha) {
// final ImageCaptcha captcha = (ImageCaptcha) rawCaptcha;
// System.out.println(captcha.getImageURL());
// try {
// captcha.setAnswer(new BufferedReader(new InputStreamReader(
// System.in)).readLine());
// System.out.println("Answer is: " + captcha.getAnswer());
// return true;
// } catch (IOException e) {
// return false;
// }
// }
// });
//
// final DownloadChannel channel = service.getDownloader(
// new URL("http://www.uploadking.com/WM3PHD9JAY")).openChannel(512);
// System.out.println(new String(ChannelUtils.toByteArray(channel)));
// }
@Test
public void testDownloader() throws IOException {
final Properties p = new Properties();
p.load(Files.newInputStream(
Paths.get("../../httpchannel-captcha/src/test/resources/captchatrader.properties"),
StandardOpenOption.READ));
final CaptchaService<?> s = new CaptchaTraderService();
s.authenticate(p.getProperty("username"), p.getProperty("password"));
service.setCaptchaService(s);
final DownloadChannel channel = service.getDownloader(
new URL("http://www.uploadking.com/WM3PHD9JAY")).openChannel(0);
System.out.println(new String(ChannelUtils.toByteArray(channel)));
}
}

View File

@@ -0,0 +1,13 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>httpchannel-service</artifactId>
<groupId>com.rogiel.httpchannel</groupId>
<version>1.0.0</version>
<relativePath>..</relativePath>
</parent>
<artifactId>httpchannel-service-zshare</artifactId>
<groupId>com.rogiel.httpchannel.services</groupId>
<name>HttpChannel/Service/ZShare</name>
<description>Provides download and upload access to zshare.com</description>
</project>

View File

@@ -0,0 +1,262 @@
package com.rogiel.httpchannel.service.impl;
import com.rogiel.httpchannel.service.AbstractHttpService;
import com.rogiel.httpchannel.service.Service;
import com.rogiel.httpchannel.service.ServiceID;
/**
* This service handles uploads to UploadKing.com.
*
* @author <a href="http://www.rogiel.com/">Rogiel</a>
* @since 1.0
*/
public class ZShareService extends AbstractHttpService implements Service/*
* ,
* UploadService
* <
* ZShareUploaderConfiguration
* >,
* DownloadService
* <
* NullDownloaderConfiguration
* >,
* AuthenticationService
* <
* NullAuthenticatorConfiguration
* >
*/{
/**
* This service ID
*/
public static final ServiceID SERVICE_ID = ServiceID.create("zshare");
// private static final Pattern UPLOAD_URL_PATTERN = Pattern
// .compile("http://dl([0-9]*)\\.zshare\\.net(\\:[0-9]*)?/",
// Pattern.CASE_INSENSITIVE);
// private static final Pattern DOWNLOAD_ID_PATTERN = Pattern
// .compile("\"downloadid\":\"([0-9a-zA-Z]*)\"");
// private static final Pattern DOWNLOAD_URL_PATTERN = Pattern
// .compile("http://(www\\.)?uploadking.\\com/[0-9A-z]*");
// private static final Pattern TIMER_PATTERN = Pattern.compile(
// "count = ([0-9]*);", Pattern.COMMENTS);
// private static final Pattern DIERCT_DOWNLOAD_URL_PATTERN = Pattern
// .compile("(http:\\\\/\\\\/www[0-9]*\\.uploadking\\.com(:[0-9]*)?\\\\/files\\\\/([0-9A-z]*)\\\\/(.*))\"");
//
// private static final String INVALID_LOGIN_STRING = "Incorrect username and/or password. Please try again!";
@Override
public ServiceID getID() {
return SERVICE_ID;
}
@Override
public int getMajorVersion() {
return 1;
}
@Override
public int getMinorVersion() {
return 0;
}
// @Override
// public Uploader<ZShareUploaderConfiguration> getUploader(String filename,
// long filesize, ZShareUploaderConfiguration configuration) {
// return new UploaderImpl(filename, filesize, configuration);
// }
//
// @Override
// public Uploader<ZShareUploaderConfiguration> getUploader(String filename,
// long filesize) {
// return getUploader(filename, filesize, newUploaderConfiguration());
// }
//
// @Override
// public ZShareUploaderConfiguration newUploaderConfiguration() {
// return new ZShareUploaderConfiguration();
// }
//
// @Override
// public long getMaximumFilesize() {
// return 1 * 1024 * 1024 * 1024;
// }
//
// @Override
// public String[] getSupportedExtensions() {
// return null;
// }
//
// @Override
// public CapabilityMatrix<UploaderCapability> getUploadCapabilities() {
// return new CapabilityMatrix<UploaderCapability>(
// UploaderCapability.UNAUTHENTICATED_UPLOAD,
// UploaderCapability.NON_PREMIUM_ACCOUNT_UPLOAD,
// UploaderCapability.PREMIUM_ACCOUNT_UPLOAD);
// }
// @Override
// public Downloader<NullDownloaderConfiguration> getDownloader(URL url,
// NullDownloaderConfiguration configuration) {
// return new DownloaderImpl(url, configuration);
// }
//
// @Override
// public Downloader<NullDownloaderConfiguration> getDownloader(URL url) {
// return getDownloader(url, newDownloaderConfiguration());
// }
//
// @Override
// public NullDownloaderConfiguration newDownloaderConfiguration() {
// return NullDownloaderConfiguration.SHARED_INSTANCE;
// }
//
// @Override
// public boolean matchURL(URL url) {
// return DOWNLOAD_URL_PATTERN.matcher(url.toString()).matches();
// }
//
// @Override
// public CapabilityMatrix<DownloaderCapability> getDownloadCapabilities() {
// return new CapabilityMatrix<DownloaderCapability>(
// DownloaderCapability.UNAUTHENTICATED_DOWNLOAD,
// DownloaderCapability.UNAUTHENTICATED_RESUME,
// DownloaderCapability.NON_PREMIUM_ACCOUNT_DOWNLOAD,
// DownloaderCapability.NON_PREMIUM_ACCOUNT_RESUME);
// }
//
// @Override
// public Authenticator<NullAuthenticatorConfiguration> getAuthenticator(
// Credential credential, NullAuthenticatorConfiguration configuration) {
// return new AuthenticatorImpl(credential, configuration);
// }
//
// @Override
// public Authenticator<NullAuthenticatorConfiguration> getAuthenticator(
// Credential credential) {
// return getAuthenticator(credential, newAuthenticatorConfiguration());
// }
//
// @Override
// public NullAuthenticatorConfiguration newAuthenticatorConfiguration() {
// return NullAuthenticatorConfiguration.SHARED_INSTANCE;
// }
//
// @Override
// public CapabilityMatrix<AuthenticatorCapability>
// getAuthenticationCapability() {
// return new CapabilityMatrix<AuthenticatorCapability>();
// }
// protected class UploaderImpl extends
// AbstractUploader<ZShareUploaderConfiguration> implements
// Uploader<ZShareUploaderConfiguration>,
// LinkedUploadChannelCloseCallback {
// private Future<String> uploadFuture;
//
// public UploaderImpl(String filename, long filesize,
// ZShareUploaderConfiguration configuration) {
// super(filename, filesize, configuration);
// }
//
// @Override
// public UploadChannel openChannel() throws IOException {
// final HTMLPage page = get("http://www.zshare.net/").asPage();
//
// final String url = page.findFormAction(UPLOAD_URL_PATTERN);
// System.out.println(url+"cgi-bin/ubr_upload.pl");
//
// final LinkedUploadChannel channel = createLinkedChannel(this);
// uploadFuture =
// multipartPost(url+"cgi-bin/ubr_upload.pl").parameter("file", channel)
// .parameter("descr", configuration.description())
// .parameter("TOS", true).parameter("is_private", false)
// .asStringAsync();
// return waitChannelLink(channel, uploadFuture);
// }
//
// @Override
// public String finish() throws IOException {
// try {
// System.out.println(uploadFuture.get());
// final String linkId = PatternUtils.find(DOWNLOAD_ID_PATTERN,
// uploadFuture.get(), 1);
// if (linkId == null)
// return null;
// return new StringBuilder("http://www.uploadking.com/").append(
// linkId).toString();
// } catch (InterruptedException e) {
// return null;
// } catch (ExecutionException e) {
// ExceptionUtils.asIOException(e);
// return null;
// }
// }
// }
// protected class DownloaderImpl extends
// AbstractHttpDownloader<NullDownloaderConfiguration> implements
// Downloader<NullDownloaderConfiguration> {
// public DownloaderImpl(URL url, NullDownloaderConfiguration configuration)
// {
// super(url, configuration);
// }
//
// @Override
// public DownloadChannel openChannel(DownloadListener listener,
// long position) throws IOException {
// HTMLPage page = get(url).asPage();
//
// final int waitTime = page.findScriptAsInt(TIMER_PATTERN, 1) * 1000;
//
// // final ReCaptcha captcha = captchaService.create(page.toString());
// // if (captcha != null) {
// // final long start = System.currentTimeMillis();
// //
// // resolveCaptcha(captcha);
// //
// // final long delta = System.currentTimeMillis() - start;
// // if (delta < waitTime)
// // timer(listener, waitTime - delta);
// //
// // String content = post(url)
// // .parameter("recaptcha_challenge_field", captcha.getID())
// // .parameter("recaptcha_response_field",
// // captcha.getAnswer()).asString();
// // String downloadLink = PatternUtils.find(
// // DIERCT_DOWNLOAD_URL_PATTERN, content, 1);
// // if (downloadLink == null)
// // throw new InvalidCaptchaException();
// // downloadLink = downloadLink.replaceAll(Pattern.quote("\\/"),
// // "/");
// // return download(get(downloadLink).position(position));
// // }
// throw new DownloadLinkNotFoundException();
// }
// }
// protected class AuthenticatorImpl extends
// AbstractAuthenticator<NullAuthenticatorConfiguration> implements
// Authenticator<NullAuthenticatorConfiguration> {
// public AuthenticatorImpl(Credential credential,
// NullAuthenticatorConfiguration configuration) {
// super(credential, configuration);
// }
//
// @Override
// public void login() throws IOException {
// final HTMLPage page = post("http://www.uploadking.com/login")
// .parameter("do", "login")
// .parameter("username", credential.getUsername())
// .parameter("password", credential.getPassword()).asPage();
// if (page.contains(INVALID_LOGIN_STRING))
// throw new AuthenticationInvalidCredentialException();
// }
//
// @Override
// public void logout() throws IOException {
// post("http://www.uploadking.com/login").parameter("do", "logout")
// .request();
// // TODO check logout status
// }
// }
}

View File

@@ -0,0 +1,28 @@
package com.rogiel.httpchannel.service.impl;
import com.rogiel.httpchannel.service.Uploader.DescriptionableUploaderConfiguration;
import com.rogiel.httpchannel.service.Uploader.UploaderConfiguration;
/**
* Describes an configuration for an {@link UploaderImpl}
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class ZShareUploaderConfiguration implements UploaderConfiguration,
DescriptionableUploaderConfiguration {
/**
* The upload description
*/
private String description = DescriptionableUploaderConfiguration.DEFAULT_DESCRIPTION;
@Override
public String description() {
return description;
}
@Override
public ZShareUploaderConfiguration description(String description) {
this.description = description;
return this;
}
}

View File

@@ -0,0 +1 @@
com.rogiel.httpchannel.service.impl.ZShareService

View File

@@ -0,0 +1,3 @@
This is a simple upload test file.
This is for testing purposes only.

View File

@@ -48,13 +48,6 @@
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.htmlparser</groupId>
<artifactId>htmlparser</artifactId>

View File

@@ -1,26 +0,0 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
import java.io.IOException;
import com.rogiel.httpchannel.util.htmlparser.HTMLPage;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public abstract class AbstractHTMLImageCaptchaService<C extends AbstractImageCaptcha>
extends AbstractImageCaptchaService<C> {
@Override
public final C create(String html) {
try {
return create(HTMLPage.parse(html));
} catch (IOException e) {
return null;
}
}
public abstract C create(HTMLPage page) throws IOException;
}

View File

@@ -1,47 +0,0 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
import java.net.URL;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public abstract class AbstractImageCaptcha implements ImageCaptcha {
private final URL imageURL;
private final String ID;
private String answer;
private boolean automaticallyResolved;
public AbstractImageCaptcha(URL imageURL, String ID) {
this.imageURL = imageURL;
this.ID = ID;
}
@Override
public void setAnswer(String answer) {
this.answer = answer;
}
@Override
public String getAnswer() {
return answer;
}
@Override
public boolean wasAutomaticallyResolved() {
return automaticallyResolved;
}
@Override
public URL getImageURL() {
return imageURL;
}
public String getID() {
return ID;
}
}

View File

@@ -1,41 +0,0 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
import java.net.URL;
import com.rogiel.httpchannel.http.GetRequest;
import com.rogiel.httpchannel.http.HttpContext;
import com.rogiel.httpchannel.http.PostMultipartRequest;
import com.rogiel.httpchannel.http.PostRequest;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public abstract class AbstractImageCaptchaService<C extends AbstractImageCaptcha>
implements ImageCaptchaService<C> {
protected final HttpContext http = new HttpContext();
@Override
public boolean resolve(C captcha) {
return false;
}
public GetRequest get(String url) {
return http.get(url);
}
public GetRequest get(URL url) {
return http.get(url);
}
public PostRequest post(String url) {
return http.post(url);
}
public PostMultipartRequest multipartPost(String url) {
return http.multipartPost(url);
}
}

View File

@@ -0,0 +1,58 @@
/**
*
*/
package com.rogiel.httpchannel.captcha;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Pattern;
import com.rogiel.httpchannel.http.HttpContext;
import com.rogiel.httpchannel.util.PatternUtils;
import com.rogiel.httpchannel.util.htmlparser.HTMLPage;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ReCaptchaExtractor {
private static final Pattern CAPTCHA_ID_PATTERN = Pattern
.compile("Recaptcha\\.create\\(\"([0-9A-z|_|\\-]*)\", ");
private static final Pattern CAPTCHA_URL_PATTERN = Pattern
.compile("http://www\\.google\\.com/recaptcha/api/challenge\\?k=([0-9A-z|\\-]*)(&(.*))?");
private static final Pattern CAPTCHA_IMAGE_PATTERN = Pattern
.compile("challenge : '(.*)'");
private static final String CHALLENGE_BASE_URL = "http://www.google.com/recaptcha/api/challenge?ajax=1&k=";
private static final String IMAGE_BASE_URL = "http://www.google.com/recaptcha/api/image?c=";
public static ImageCaptcha extractCaptcha(HTMLPage page, HttpContext ctx) {
final String url = page.findScriptSrc(CAPTCHA_URL_PATTERN);
if (url == null)
return null;
try {
return doExtract(ctx.get(url).asString());
} catch (IOException e) {
return null;
}
}
public static ImageCaptcha extractAjaxCaptcha(HTMLPage page, HttpContext ctx) {
final String siteID = page.findScript(CAPTCHA_ID_PATTERN, 1);
try {
return doExtract(ctx.get(CHALLENGE_BASE_URL + siteID).asString());
} catch (IOException e) {
return null;
}
}
private static ImageCaptcha doExtract(String content) {
final String id = PatternUtils.find(CAPTCHA_IMAGE_PATTERN, content, 1);
try {
return new ImageCaptcha(id, new URL(IMAGE_BASE_URL + id));
} catch (MalformedURLException e) {
return null;
}
}
}

View File

@@ -23,6 +23,8 @@ import org.apache.commons.io.FilenameUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.rogiel.httpchannel.http.Request;
import com.rogiel.httpchannel.service.Downloader.DownloaderConfiguration;
@@ -35,6 +37,8 @@ import com.rogiel.httpchannel.util.ThreadUtils;
*/
public abstract class AbstractHttpDownloader<C extends DownloaderConfiguration>
extends AbstractDownloader<C> implements Downloader<C> {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
protected AbstractHttpDownloader(URL url, C configuration) {
super(url, configuration);
}
@@ -54,6 +58,7 @@ public abstract class AbstractHttpDownloader<C extends DownloaderConfiguration>
if (!listener.timer(timer))
return;
}
logger.debug("Download timer waiting {}", timer);
ThreadUtils.sleep(timer);
}

View File

@@ -38,6 +38,7 @@ public abstract class AbstractHttpService extends AbstractService implements
protected LinkedUploadChannel waitChannelLink(LinkedUploadChannel channel,
Future<?> future) {
logger.debug("Waiting channel {} to link", channel);
while (!channel.isLinked() && !future.isDone()) {
ThreadUtils.sleep(100);
}

View File

@@ -22,6 +22,9 @@ import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.WritableByteChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.rogiel.httpchannel.service.UploadChannel;
import com.rogiel.httpchannel.service.exception.UploadLinkNotFoundException;
@@ -30,6 +33,8 @@ import com.rogiel.httpchannel.service.exception.UploadLinkNotFoundException;
*
*/
public class LinkedUploadChannel implements UploadChannel {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private WritableByteChannel channel;
private final LinkedUploadChannelCloseCallback closeCallback;
@@ -69,6 +74,7 @@ public class LinkedUploadChannel implements UploadChannel {
public void close() throws IOException {
open = false;
final String downloadLink = closeCallback.finish();
logger.debug("Download link returned by service is {}", downloadLink);
if (downloadLink == null)
throw new UploadLinkNotFoundException();
this.downloadLink = new URL(downloadLink);

View File

@@ -0,0 +1,27 @@
/**
*
*/
package com.rogiel.httpchannel.util;
import java.io.IOException;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ExceptionUtils {
public static void asIOException(Exception e) throws IOException {
final Throwable e2 = e.getCause();
if (e2 == null) {
throw new IOException(e);
} else if (e instanceof IOException) {
throw (IOException) e;
} else if (e2 instanceof IOException) {
throw (IOException) e2;
} else if (e2 instanceof RuntimeException) {
throw (RuntimeException) e2;
} else {
throw new IOException(e);
}
}
}

13
pom.xml
View File

@@ -64,6 +64,19 @@
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.6.4</version>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
</dependencies>
<url>http://httpchannel.rogiel.com/</url>
</project>