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

Several API improvements and MegaUpload direct link fix

This commit is contained in:
2011-09-08 13:28:21 -03:00
parent da1e2c46b7
commit 5406d14cbf
30 changed files with 827 additions and 219 deletions

View File

@@ -16,29 +16,37 @@
*/
package com.rogiel.httpchannel.service;
import java.io.IOException;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import com.rogiel.httpchannel.service.DownloadListener.TimerWaitReason;
import com.rogiel.httpchannel.util.ThreadUtils;
/**
* @author rogiel
*/
public abstract class AbstractDownloader implements Downloader {
protected void timer(DownloadListener listener, long timer) {
listener.timer(timer, TimerWaitReason.DOWNLOAD_TIMER);
ThreadUtils.sleep(timer);
protected int parseTimer(String stringTimer) {
int timer = 0;
if (stringTimer != null && stringTimer.length() > 0) {
timer = Integer.parseInt(stringTimer);
}
return timer;
}
protected boolean cooldown(DownloadListener listener, long cooldown)
throws IOException {
if (listener.timer(cooldown, TimerWaitReason.COOLDOWN)) {
ThreadUtils.sleep(cooldown);
return true;
} else {
throw new IOException("Timer " + TimerWaitReason.COOLDOWN
+ " aborted due to listener request");
protected long getContentLength(HttpResponse response) {
final Header contentLengthHeader = response
.getFirstHeader("Content-Length");
long contentLength = -1;
if (contentLengthHeader != null) {
contentLength = Long.valueOf(contentLengthHeader.getValue());
}
return contentLength;
}
protected void timer(DownloadListener listener, long timer) {
if (listener != null) {
listener.timer(timer);
}
ThreadUtils.sleep(timer);
}
}

View File

@@ -19,6 +19,7 @@ package com.rogiel.httpchannel.service;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import com.rogiel.httpchannel.service.captcha.CaptchaResolver;
import com.rogiel.httpchannel.service.config.ServiceConfiguration;
import com.rogiel.httpchannel.util.AlwaysRedirectStrategy;
@@ -35,6 +36,11 @@ public abstract class AbstractHttpService<T extends ServiceConfiguration>
*/
protected DefaultHttpClient client = new DefaultHttpClient();
/**
* The captcha resolver
*/
protected CaptchaResolver captchaResolver;
protected AbstractHttpService(T configuration) {
super(configuration);
client.setRedirectStrategy(new AlwaysRedirectStrategy());

View File

@@ -18,6 +18,8 @@ package com.rogiel.httpchannel.service;
import java.io.IOException;
import com.rogiel.httpchannel.service.exception.AuthenticationInvalidCredentialException;
/**
* This interfaces provides authentication for an service.
*
@@ -31,15 +33,19 @@ public interface Authenticator {
* <b>Note</b>: If you want to logout the user, see
* {@link Authenticator#logout()}
*
* @return true if login was successful
* @throws IOException
* if any IO error occur
* @throws AuthenticationInvalidCredentialException
* if the credentials are not valid or cannot be used
*/
boolean login() throws IOException;
void login() throws IOException, AuthenticationInvalidCredentialException;
/**
* Logout into the {@link Service}. The session is restored to an not
* logged-in state.
*
* @return true if logout was successful
* @throws IOException
* if any IO error occur
*/
boolean logout() throws IOException;
void logout() throws IOException;
}

View File

@@ -16,13 +16,29 @@
*/
package com.rogiel.httpchannel.service;
import java.nio.channels.Channel;
import java.nio.channels.ReadableByteChannel;
/**
* This is an {@link Channel} for downloads. Any data to be downloaded, must be
* Redden from this channel.
* <p>
* Since this {@link Channel} <tt>implements</tt> {@link ReadableByteChannel}
* you can treat it as any other regular IO {@link Channel}.
* <p>
* <b>Remember</b>: always close the {@link Channel}, if you do otherwise, the
* resources will not be freed and will consume machine resources.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface DownloadChannel extends ReadableByteChannel {
long getLength();
/**
* @return the file size
*/
long getFilesize();
/**
* @return the file name
*/
String getFilename();
}

View File

@@ -16,8 +16,6 @@
*/
package com.rogiel.httpchannel.service;
import com.rogiel.httpchannel.service.captcha.Captcha;
/**
* This listener keeps an track on the progress on an {@link Downloader}
* service.
@@ -32,39 +30,7 @@ public interface DownloadListener {
*
* @param time
* the time in ms in which the service will be be waiting.
* @param reason
* the reason why this timer is running
* @return true if desires to wait, false otherwise
*/
boolean timer(long time, TimerWaitReason reason);
/**
* The reason why an certain timer is being ran.
*
* @author Rogiel
*/
public enum TimerWaitReason {
/**
* Normal download timer. An annoyance.
*/
DOWNLOAD_TIMER,
/**
* This IP has already download up to the limit, waiting for releasing
* of the block.
*/
COOLDOWN,
/**
* This is an unknown wait time.
*/
UNKNOWN;
}
/**
* Passes an captcha by parameter and waits for the response of the
* challenge.
*
* @param captcha
* the captcha challenge
*/
String captcha(Captcha captcha);
boolean timer(long time);
}

View File

@@ -43,6 +43,9 @@ public interface DownloadService extends Service {
/**
* Check if this {@link Service} can download from this URL. Implemtations
* might or might not perform network activity.
* <p>
* <b>Please note</b> that the value returned by this method may vary based
* on it's state (i.e. premium or not).
*
* @param url
* the {@link URL} to be tested.

View File

@@ -18,6 +18,9 @@ package com.rogiel.httpchannel.service;
import java.io.IOException;
import com.rogiel.httpchannel.service.exception.DownloadLimitExceededException;
import com.rogiel.httpchannel.service.exception.DownloadLinkNotFoundException;
/**
* This interfaces provides downloading for an service.
*
@@ -30,6 +33,17 @@ public interface Downloader {
*
* @param listener
* the listener to keep a track on the download progress
*
* @return the {@link DownloadChannel} instance
* @throws IOException
* if any IO error occur
* @throws DownloadLinkNotFoundException
* if the direct download link cannot be found (the file could
* have been deleted)
* @throws DownloadLimitExceededException
* if the download limit has been exceed, most times thrown when
* downloading as a non-premium user
*/
DownloadChannel download(DownloadListener listener) throws IOException;
DownloadChannel download(DownloadListener listener) throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException;
}

View File

@@ -36,7 +36,7 @@ public interface Service {
*
* @return the id of the service
*/
String getId();
String getID();
/**
* Get Major version of this service

View File

@@ -16,15 +16,48 @@
*/
package com.rogiel.httpchannel.service;
import java.io.IOException;
import java.nio.channels.Channel;
import java.nio.channels.WritableByteChannel;
import com.rogiel.httpchannel.service.exception.UploadLinkNotFoundException;
/**
* This is an {@link Channel} for uploads. Any data to be uploaded, must be
* written into this channel.
* <p>
* Since this {@link Channel} <tt>implements</tt> {@link WritableByteChannel}
* you can treat it as any other regular IO {@link Channel}.
* <p>
* <b>Remember</b>: always close the {@link Channel}, if you do otherwise, your
* upload will not finish and will never return the link.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public interface UploadChannel extends WritableByteChannel {
long getLength();
/**
* @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
* an exception, this method might return <tt>null</tt>.
*
* @return the download link for this upload
*/
String getDownloadLink();
/**
* @throws UploadLinkNotFoundException
* if after the upload, the download link cannot be found
*/
@Override
void close() throws IOException, UploadLinkNotFoundException;
}

View File

@@ -64,7 +64,7 @@ public class UploadListenerContentBody extends AbstractContentBody {
@Override
public long getContentLength() {
return channel.getLength();
return channel.getFilesize();
}
@Override

View File

@@ -28,8 +28,10 @@ public interface UploadService extends Service {
* with the parent {@link Service} instance.<br>
* <b>Note</b>: not all services might support <tt>description</tt>
*
* @param file
* the file to be uploaded
* @param filename
* the name of the file to be uploaded
* @param filesize
* the size of the file to be uploaded. This must be exact.
* @param description
* the description of the upload. If supported.
* @return the new {@link Uploader} instance
@@ -38,6 +40,9 @@ public interface UploadService extends Service {
/**
* Get the maximum upload file size supported by this service.
* <p>
* <b>Please note</b> that the value returned by this method may vary based
* on it's state (i.e. premium or not).
*
* @return the maximum filesize supported
*/
@@ -46,6 +51,9 @@ public interface UploadService extends Service {
/**
* Get the list of all supported extensions. Might return <tt>null</tt> if
* there is no restriction.
* <p>
* <b>Please note</b> that the value returned by this method may vary based
* on it's state (i.e. premium or not).
*
* @return the list of supported file extensions. Can return <tt>null</tt>
* if there is not restriction

View File

@@ -28,11 +28,9 @@ public interface Uploader {
/**
* Starts the upload process on this service.
*
* @param listener
* the listener do keep an track on the upload process
* @throws UploadServiceException
* thrown if something went wrong
* @return the {@link UploadChannel} instance
* @throws IOException
* if any IO error occur
*/
UploadChannel upload() throws IOException;
}

View File

@@ -14,28 +14,19 @@
* 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;
import java.io.IOException;
package com.rogiel.httpchannel.service.captcha;
/**
* Base exception for any {@link Service}.
*
* @author Rogiel
* @since 1.0
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ServiceException extends IOException {
private static final long serialVersionUID = 1L;
public ServiceException(String message) {
super(message);
}
public ServiceException(Throwable t) {
super(t);
}
public ServiceException(String message, Throwable t) {
super(message, t);
}
public interface CaptchaResolver {
/**
* Passes an captcha by parameter and waits for the response of the
* challenge.
*
* @param captcha
* the captcha challenge
*/
String resolve(Captcha captcha);
}

View File

@@ -58,7 +58,7 @@ public class InputStreamDownloadChannel implements DownloadChannel {
}
@Override
public long getLength() {
public long getFilesize() {
return length;
}

View File

@@ -67,7 +67,7 @@ public class LinkedUploadChannel implements UploadChannel {
}
@Override
public long getLength() {
public long getFilesize() {
return length;
}

View File

@@ -0,0 +1,61 @@
/*
* 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.exception;
/**
* Exception thrown if the authentication credential is not valid.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class AuthenticationInvalidCredentialException extends
AuthenticationServiceException {
private static final long serialVersionUID = 1L;
/**
* Creates a new empty instance of this exception
*/
public AuthenticationInvalidCredentialException() {
super();
}
/**
* @param message
* the message
* @param cause
* the root cause
*/
public AuthenticationInvalidCredentialException(String message,
Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public AuthenticationInvalidCredentialException(String message) {
super(message);
}
/**
* @param cause
* the root cause
*/
public AuthenticationInvalidCredentialException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,51 @@
/*
* 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.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class AuthenticationServiceException extends ChannelServiceException {
private static final long serialVersionUID = 1L;
public AuthenticationServiceException() {
super();
}
/**
* @param message
* @param cause
*/
public AuthenticationServiceException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
*/
public AuthenticationServiceException(String message) {
super(message);
}
/**
* @param cause
*/
public AuthenticationServiceException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,53 @@
/*
* 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.exception;
import java.io.IOException;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class ChannelServiceException extends IOException {
private static final long serialVersionUID = 1L;
public ChannelServiceException() {
super();
}
/**
* @param message
* @param cause
*/
public ChannelServiceException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
*/
public ChannelServiceException(String message) {
super(message);
}
/**
* @param cause
*/
public ChannelServiceException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,62 @@
/*
* 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.exception;
import com.rogiel.httpchannel.service.captcha.CaptchaResolver;
/**
* Exception thrown if the {@link CaptchaResolver} has returned an invalid
* captcha
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class DownloadInvalidCaptchaException extends DownloadServiceException {
private static final long serialVersionUID = 1L;
/**
* Creates a new empty instance of this exception
*/
public DownloadInvalidCaptchaException() {
super();
}
/**
* @param message
* the message
* @param cause
* the root cause
*/
public DownloadInvalidCaptchaException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public DownloadInvalidCaptchaException(String message) {
super(message);
}
/**
* @param cause
* the root cause
*/
public DownloadInvalidCaptchaException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.exception;
/**
* Exception thrown if the download limit has been exceeded.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class DownloadLimitExceededException extends DownloadServiceException {
private static final long serialVersionUID = 1L;
/**
* Creates a new empty instance of this exception
*/
public DownloadLimitExceededException() {
super();
}
/**
* @param message
* the message
* @param cause
* the root cause
*/
public DownloadLimitExceededException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public DownloadLimitExceededException(String message) {
super(message);
}
/**
* @param cause
* the root cause
*/
public DownloadLimitExceededException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.exception;
/**
* Exception thrown if the direct download link could not be found.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class DownloadLinkNotFoundException extends DownloadServiceException {
private static final long serialVersionUID = 1L;
/**
* Creates a new empty instance of this exception
*/
public DownloadLinkNotFoundException() {
super();
}
/**
* @param message
* the message
* @param cause
* the root cause
*/
public DownloadLinkNotFoundException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public DownloadLinkNotFoundException(String message) {
super(message);
}
/**
* @param cause
* the root cause
*/
public DownloadLinkNotFoundException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,51 @@
/*
* 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.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class DownloadServiceException extends ChannelServiceException {
private static final long serialVersionUID = 1L;
public DownloadServiceException() {
super();
}
/**
* @param message
* @param cause
*/
public DownloadServiceException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
*/
public DownloadServiceException(String message) {
super(message);
}
/**
* @param cause
*/
public DownloadServiceException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,59 @@
/*
* 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.exception;
/**
* Exception thrown if the download link could not be located after the upload.
*
* @author <a href="http://www.rogiel.com">Rogiel</a>
*/
public class UploadLinkNotFoundException extends UploadServiceException {
private static final long serialVersionUID = 1L;
/**
* Creates a new empty instance of this exception
*/
public UploadLinkNotFoundException() {
super();
}
/**
* @param message
* the message
* @param cause
* the root cause
*/
public UploadLinkNotFoundException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
* the message
*/
public UploadLinkNotFoundException(String message) {
super(message);
}
/**
* @param cause
* the root cause
*/
public UploadLinkNotFoundException(Throwable cause) {
super(cause);
}
}

View File

@@ -0,0 +1,51 @@
/*
* 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.exception;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class UploadServiceException extends ChannelServiceException {
private static final long serialVersionUID = 1L;
public UploadServiceException() {
super();
}
/**
* @param message
* @param cause
*/
public UploadServiceException(String message, Throwable cause) {
super(message, cause);
}
/**
* @param message
*/
public UploadServiceException(String message) {
super(message);
}
/**
* @param cause
*/
public UploadServiceException(Throwable cause) {
super(cause);
}
}

View File

@@ -24,7 +24,6 @@ import java.util.regex.Pattern;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
@@ -54,6 +53,7 @@ import com.rogiel.httpchannel.service.channel.InputStreamDownloadChannel;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannel;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannel.LinkedUploadChannelCloseCallback;
import com.rogiel.httpchannel.service.config.ServiceConfiguration;
import com.rogiel.httpchannel.service.exception.AuthenticationInvalidCredentialException;
import com.rogiel.httpchannel.service.impl.HotFileService.HotFileServiceConfiguration;
import com.rogiel.httpchannel.util.HttpClientUtils;
import com.rogiel.httpchannel.util.PatternUtils;
@@ -73,20 +73,35 @@ public class HotFileService extends
private static final Pattern DOWNLOAD_DIRECT_LINK_PATTERN = Pattern
.compile("http://hotfile\\.com/get/([0-9]*)/([A-Za-z0-9]*)/([A-Za-z0-9]*)/([^\"]*)");
private static final Pattern DOWNLOAD_TIMER = Pattern
.compile("timerend=d\\.getTime\\(\\)\\+([0-9]*);");
// private static final Pattern DOWNLOAD_TIMER = Pattern
// .compile("timerend=d\\.getTime\\(\\)\\+([0-9]*);");
// private static final Pattern DOWNLOAD_FILESIZE = Pattern
// .compile("[0-9]*(\\.[0-9]*)? (K|M|G)B");
private static final Pattern DOWNLOAD_URL_PATTERN = Pattern
.compile("http://hotfile\\.com/dl/([0-9]*)/([A-Za-z0-9]*)/([^\"]*)");
// private static final Pattern FREE_DOWNLOAD_URL_PATTERN = Pattern
// .compile("/dl/([0-9]*)/([A-Za-z0-9]*)/([^\"]*)");
// private static final Pattern DOWNLOAD_ACTION_PATTERN = Pattern
// .compile("name=action value=([A-Za-z0-9]*)");
// private static final Pattern DOWNLOAD_TM_PATTERN = Pattern
// .compile("name=tm value=([A-Za-z0-9]*)");
// private static final Pattern DOWNLOAD_TMHASH_PATTERN = Pattern
// .compile("name=tmhash value=([A-Za-z0-9]*)");
// private static final Pattern DOWNLOAD_WAIT_PATTERN = Pattern
// .compile("name=wait value=([A-Za-z0-9]*)");
// private static final Pattern DOWNLOAD_WAITHASH_PATTERN = Pattern
// .compile("name=waithash value=([A-Za-z0-9]*)");
// private static final Pattern DOWNLOAD_UPIDHASH_PATTERN = Pattern
// .compile("name=upidhash value=([A-Za-z0-9]*)");
public HotFileService(final HotFileServiceConfiguration configuration) {
super(configuration);
}
@Override
public String getId() {
public String getID() {
return "hotfile";
}
@@ -137,8 +152,6 @@ public class HotFileService extends
@Override
public CapabilityMatrix<DownloaderCapability> getDownloadCapabilities() {
return new CapabilityMatrix<DownloaderCapability>(
DownloaderCapability.UNAUTHENTICATED_DOWNLOAD,
DownloaderCapability.NON_PREMIUM_ACCOUNT_DOWNLOAD,
DownloaderCapability.PREMIUM_ACCOUNT_DOWNLOAD);
}
@@ -167,7 +180,7 @@ public class HotFileService extends
@Override
public UploadChannel upload() throws IOException {
final String body = HttpClientUtils.get(client,
final String body = HttpClientUtils.getString(client,
"http://www.hotfile.com/");
final String url = PatternUtils.find(UPLOAD_URL_PATTERN, body);
@@ -215,36 +228,75 @@ public class HotFileService extends
final String content = IOUtils.toString(response.getEntity()
.getContent());
// try to find timer
final String stringTimer = PatternUtils.find(DOWNLOAD_TIMER,
content, 2, 1);
int timer = 0;
if (stringTimer != null && stringTimer.length() > 0) {
timer = Integer.parseInt(stringTimer);
}
if (timer > 0) {
cooldown(listener, timer);
return download(listener);
}
// // try to find timer
// final String stringTimer = PatternUtils.find(DOWNLOAD_TIMER,
// content, 2, 1);
// int timer = 0;
// if (stringTimer != null && stringTimer.length() > 0) {
// timer = Integer.parseInt(stringTimer);
// }
// if (timer > 0) {
// throw new DownloadLimitExceededException("Must wait " + timer
// + " milliseconds");
// }
final String downloadUrl = PatternUtils.find(
DOWNLOAD_DIRECT_LINK_PATTERN, content, 0);
// final String tmHash = PatternUtils.find(DOWNLOAD_TMHASH_PATTERN,
// content);F
if (downloadUrl != null && downloadUrl.length() > 0) {
final HttpGet downloadRequest = new HttpGet(downloadUrl);
final HttpResponse downloadResponse = client
.execute(downloadRequest);
final String filename = FilenameUtils.getName(downloadUrl);
final Header contentLengthHeader = downloadResponse
.getFirstHeader("Content-Length");
long contentLength = -1;
if (contentLengthHeader != null) {
contentLength = Long
.valueOf(contentLengthHeader.getValue());
}
final String filename = FilenameUtils.getName(downloadUrl);
long contentLength = getContentLength(downloadResponse);
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");
}
@@ -259,7 +311,7 @@ public class HotFileService extends
}
@Override
public boolean login() throws ClientProtocolException, IOException {
public void login() throws ClientProtocolException, IOException {
final HttpPost login = new HttpPost(
"http://www.hotfile.com/login.php");
final MultipartEntity entity = new MultipartEntity();
@@ -272,12 +324,11 @@ public class HotFileService extends
String response = HttpClientUtils.execute(client, login);
if (response.toLowerCase().contains(
credential.getUsername().toLowerCase()))
return true;
return false;
throw new AuthenticationInvalidCredentialException();
}
@Override
public boolean logout() throws IOException {
public void logout() throws IOException {
final HttpPost logout = new HttpPost(
"http://www.megaupload.com/?c=account");
final MultipartEntity entity = new MultipartEntity();
@@ -287,8 +338,6 @@ public class HotFileService extends
HttpClientUtils.execute(client, logout);
// TODO check logout status
return true;
}
}

View File

@@ -18,19 +18,23 @@ package com.rogiel.httpchannel.service.impl;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.regex.Pattern;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.message.BasicNameValuePair;
import com.rogiel.httpchannel.service.AbstractDownloader;
import com.rogiel.httpchannel.service.AbstractHttpService;
@@ -55,6 +59,10 @@ import com.rogiel.httpchannel.service.channel.LinkedUploadChannel;
import com.rogiel.httpchannel.service.channel.LinkedUploadChannel.LinkedUploadChannelCloseCallback;
import com.rogiel.httpchannel.service.config.ServiceConfiguration;
import com.rogiel.httpchannel.service.config.ServiceConfigurationProperty;
import com.rogiel.httpchannel.service.exception.AuthenticationInvalidCredentialException;
import com.rogiel.httpchannel.service.exception.DownloadLimitExceededException;
import com.rogiel.httpchannel.service.exception.DownloadLinkNotFoundException;
import com.rogiel.httpchannel.service.exception.UploadLinkNotFoundException;
import com.rogiel.httpchannel.service.impl.MegaUploadService.MegaUploadServiceConfiguration;
import com.rogiel.httpchannel.util.HttpClientUtils;
import com.rogiel.httpchannel.util.PatternUtils;
@@ -87,7 +95,7 @@ public class MegaUploadService extends
}
@Override
public String getId() {
public String getID() {
return "megaupload";
}
@@ -111,7 +119,7 @@ public class MegaUploadService extends
public long getMaximumFilesize() {
return 1 * 1024 * 1024 * 1024;
}
@Override
public String[] getSupportedExtensions() {
return null;
@@ -171,7 +179,7 @@ public class MegaUploadService extends
@Override
public UploadChannel upload() throws IOException {
final String body = HttpClientUtils.get(client,
final String body = HttpClientUtils.getString(client,
"http://www.megaupload.com/multiupload/");
final String url = PatternUtils.find(UPLOAD_URL_PATTERN, body);
@@ -196,8 +204,11 @@ public class MegaUploadService extends
@Override
public String finish() throws IOException {
try {
return PatternUtils.find(DOWNLOAD_URL_PATTERN,
String link = PatternUtils.find(DOWNLOAD_URL_PATTERN,
uploadFuture.get());
if (link == null)
throw new UploadLinkNotFoundException();
return link;
} catch (InterruptedException e) {
return null;
} catch (ExecutionException e) {
@@ -216,18 +227,32 @@ public class MegaUploadService extends
@Override
public DownloadChannel download(DownloadListener listener)
throws IOException {
final HttpGet request = new HttpGet(url.toString());
final HttpResponse response = client.execute(request);
HttpResponse response = HttpClientUtils.get(client, url.toString());
// disable direct downloads, we don't support them!
if (response.getEntity().getContentType().getValue()
.equals("application/octet-stream")) {
final HttpPost updateAutoDownload = new HttpPost(
"http://www.megaupload.com/?c=account");
final List<NameValuePair> pairs = new ArrayList<NameValuePair>();
pairs.add(new BasicNameValuePair("do", "directdownloads"));
pairs.add(new BasicNameValuePair("accountupdate", "1"));
pairs.add(new BasicNameValuePair("set_ddl", "0"));
updateAutoDownload.setEntity(new UrlEncodedFormEntity(pairs));
// close connection
response.getEntity().getContent().close();
// execute and re-request download
response = HttpClientUtils.get(client, url.toString());
}
final String content = IOUtils.toString(response.getEntity()
.getContent());
// try to find timer
final String stringTimer = PatternUtils.find(DOWNLOAD_TIMER,
content, 1);
int timer = 0;
if (stringTimer != null && stringTimer.length() > 0) {
timer = Integer.parseInt(stringTimer);
}
int timer = parseTimer(PatternUtils
.find(DOWNLOAD_TIMER, content, 1));
if (timer > 0 && configuration.respectWaitTime()) {
timer(listener, timer * 1000);
}
@@ -241,28 +266,19 @@ public class MegaUploadService extends
if (downloadResponse.getStatusLine().getStatusCode() == HttpStatus.SC_FORBIDDEN
|| downloadResponse.getStatusLine().getStatusCode() == HttpStatus.SC_SERVICE_UNAVAILABLE) {
downloadResponse.getEntity().getContent().close();
if (cooldown(listener, 60 * 1000))
return download(listener); // retry download
throw new DownloadLimitExceededException("HTTP "
+ downloadResponse.getStatusLine().getStatusCode()
+ " response");
} else {
final String filename = FilenameUtils.getName(downloadUrl);
// listener.fileName(filename);
final Header contentLengthHeader = downloadResponse
.getFirstHeader("Content-Length");
long contentLength = -1;
if (contentLengthHeader != null) {
contentLength = Long.valueOf(contentLengthHeader
.getValue());
// listener.fileSize(contentLength);
}
final long contentLength = getContentLength(downloadResponse);
return new InputStreamDownloadChannel(downloadResponse
.getEntity().getContent(), contentLength, filename);
}
} else {
throw new IOException("Download link not found");
throw new DownloadLinkNotFoundException();
}
throw new IOException("Unknown error");
}
}
@@ -274,7 +290,7 @@ public class MegaUploadService extends
}
@Override
public boolean login() throws IOException {
public void login() throws IOException {
final HttpPost login = new HttpPost(
"http://www.megaupload.com/?c=login");
final MultipartEntity entity = new MultipartEntity();
@@ -287,12 +303,11 @@ public class MegaUploadService extends
final String response = HttpClientUtils.execute(client, login);
if (response.contains("Username and password do "
+ "not match. Please try again!"))
return false;
return true;
throw new AuthenticationInvalidCredentialException();
}
@Override
public boolean logout() throws IOException {
public void logout() throws IOException {
final HttpPost logout = new HttpPost(
"http://www.megaupload.com/?c=account");
final MultipartEntity entity = new MultipartEntity();
@@ -302,8 +317,6 @@ public class MegaUploadService extends
HttpClientUtils.execute(client, logout);
// TODO check logout status
return true;
}
}

View File

@@ -33,8 +33,14 @@ public class HttpClientUtils {
private static final ExecutorService threadPool = Executors
.newCachedThreadPool();
public static String get(HttpClient client, String url) throws IOException {
return execute(client, new HttpGet(url));
public static HttpResponse get(HttpClient client, String url)
throws IOException {
return client.execute(new HttpGet(url));
}
public static String getString(HttpClient client, String url)
throws IOException {
return toString(get(client, url));
}
public static String execute(HttpClient client, HttpUriRequest request)

View File

@@ -24,6 +24,11 @@ public class PatternUtils {
return find(pattern, text, 0);
}
public static int findInt(Pattern pattern, String text, int n) {
String found = find(pattern, text, n);
return (found != null ? Integer.parseInt(found) : 0);
}
public static String find(Pattern pattern, String text, int n) {
final Matcher matcher = pattern.matcher(text);
if (matcher.find()) {

View File

@@ -41,14 +41,13 @@ import org.junit.Test;
import com.rogiel.httpchannel.service.AuthenticationService;
import com.rogiel.httpchannel.service.Credential;
import com.rogiel.httpchannel.service.DownloadChannel;
import com.rogiel.httpchannel.service.DownloadListener;
import com.rogiel.httpchannel.service.DownloadService;
import com.rogiel.httpchannel.service.Service;
import com.rogiel.httpchannel.service.UploadChannel;
import com.rogiel.httpchannel.service.UploadService;
import com.rogiel.httpchannel.service.UploaderCapability;
import com.rogiel.httpchannel.service.captcha.Captcha;
import com.rogiel.httpchannel.service.config.ServiceConfigurationHelper;
import com.rogiel.httpchannel.service.exception.AuthenticationInvalidCredentialException;
import com.rogiel.httpchannel.service.impl.HotFileService.HotFileServiceConfiguration;
public class HotFileServiceTest {
@@ -87,19 +86,19 @@ public class HotFileServiceTest {
@Test
public void testServiceId() {
System.out.println("Service: " + service.toString());
assertEquals("hotfile", service.getId());
assertEquals("hotfile", service.getID());
}
@Test
public void testValidAuthenticator() throws IOException {
Assert.assertTrue(((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login());
((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login();
}
@Test
@Test(expected = AuthenticationInvalidCredentialException.class)
public void testInvalidAuthenticator() throws IOException {
Assert.assertFalse(((AuthenticationService) service).getAuthenticator(
new Credential(INVALID_USERNAME, INVALID_PASSWORD)).login());
((AuthenticationService) service).getAuthenticator(
new Credential(INVALID_USERNAME, INVALID_PASSWORD)).login();
}
@Test
@@ -130,8 +129,8 @@ public class HotFileServiceTest {
((UploadService) service).getUploadCapabilities().has(
UploaderCapability.PREMIUM_ACCOUNT_UPLOAD));
Assert.assertTrue(((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login());
((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login();
final UploadChannel channel = ((UploadService) service).getUploader(
"simulado_2010_1_res_all.zip",
@@ -154,20 +153,7 @@ public class HotFileServiceTest {
.getDownloader(
new URL(
"http://hotfile.com/dl/129251605/9b4faf2/simulado_2010_1_res_all.zip.html"))
.download(new DownloadListener() {
@Override
public boolean timer(long time, TimerWaitReason reason) {
System.out.println("Waiting " + time + " in " + reason);
// if (reason == TimerWaitReason.DOWNLOAD_TIMER)
// return true;
return true;
}
@Override
public String captcha(Captcha captcha) {
return null;
}
});
.download(null);
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
IOUtils.copy(Channels.newInputStream(channel), bout);
System.out.println(bout.size());
@@ -176,28 +162,14 @@ public class HotFileServiceTest {
@Test
public void testLoggedInDownloader() throws IOException,
MalformedURLException {
Assert.assertTrue(((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login());
((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login();
final DownloadChannel channel = ((DownloadService) service)
.getDownloader(
new URL(
"http://hotfile.com/dl/129251605/9b4faf2/simulado_2010_1_res_all.zip.html"))
.download(new DownloadListener() {
@Override
public boolean timer(long time, TimerWaitReason reason) {
System.out.println("Waiting " + time + " in " + reason);
if (reason == TimerWaitReason.DOWNLOAD_TIMER)
return true;
return false;
}
@Override
public String captcha(Captcha captcha) {
// TODO Auto-generated method stub
return null;
}
});
.download(null);
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
IOUtils.copy(Channels.newInputStream(channel), bout);

View File

@@ -44,8 +44,8 @@ import com.rogiel.httpchannel.service.Service;
import com.rogiel.httpchannel.service.UploadChannel;
import com.rogiel.httpchannel.service.UploadService;
import com.rogiel.httpchannel.service.UploaderCapability;
import com.rogiel.httpchannel.service.captcha.Captcha;
import com.rogiel.httpchannel.service.config.ServiceConfigurationHelper;
import com.rogiel.httpchannel.service.exception.AuthenticationInvalidCredentialException;
import com.rogiel.httpchannel.service.impl.MegaUploadService.MegaUploadServiceConfiguration;
public class MegaUploadServiceTest {
@@ -84,19 +84,19 @@ public class MegaUploadServiceTest {
@Test
public void testServiceId() {
System.out.println("Service: " + service.toString());
assertEquals("megaupload", service.getId());
assertEquals("megaupload", service.getID());
}
@Test
public void testValidAuthenticator() throws IOException {
Assert.assertTrue(((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login());
((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login();
}
@Test
@Test(expected = AuthenticationInvalidCredentialException.class)
public void testInvalidAuthenticator() throws IOException {
Assert.assertFalse(((AuthenticationService) service).getAuthenticator(
new Credential(INVALID_USERNAME, INVALID_PASSWORD)).login());
((AuthenticationService) service).getAuthenticator(
new Credential(INVALID_USERNAME, INVALID_PASSWORD)).login();
}
@Test
@@ -133,8 +133,8 @@ public class MegaUploadServiceTest {
((UploadService) service).getUploadCapabilities().has(
UploaderCapability.PREMIUM_ACCOUNT_UPLOAD));
Assert.assertTrue(((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login());
((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login();
final UploadChannel channel = ((UploadService) service).getUploader(
"test.bin", 10, "Upload by httpchannel").upload();
@@ -158,21 +158,36 @@ public class MegaUploadServiceTest {
}
@Test
public void testDownloader() throws IOException, MalformedURLException {
public void testFreeDownloader() throws IOException, MalformedURLException {
final DownloadChannel channel = ((DownloadService) service)
.getDownloader(new URL("http://www.megaupload.com/?d=CVQKJ1KM"))
.download(new DownloadListener() {
@Override
public boolean timer(long time, TimerWaitReason reason) {
System.out.println("Waiting " + time + " in " + reason);
public boolean timer(long time) {
System.out.println("Waiting " + time);
// if (reason == TimerWaitReason.DOWNLOAD_TIMER)
// return true;
return true;
}
});
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
IOUtils.copy(Channels.newInputStream(channel), bout);
System.out.println(bout.size());
}
@Test
public void testPremiumDownloader() throws IOException,
MalformedURLException {
((AuthenticationService) service).getAuthenticator(
new Credential(VALID_USERNAME, VALID_PASSWORD)).login();
final DownloadChannel channel = ((DownloadService) service)
.getDownloader(new URL("http://www.megaupload.com/?d=CVQKJ1KM"))
.download(new DownloadListener() {
@Override
public String captcha(Captcha captcha) {
return null;
public boolean timer(long time) {
System.out.println("Waiting " + time);
return true;
}
});
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
@@ -187,22 +202,15 @@ public class MegaUploadServiceTest {
MegaUploadServiceConfiguration.class, new File(
"src/test/resources/megaupload-nowait.properties")));
@SuppressWarnings("unused")
final DownloadChannel channel = ((DownloadService) service)
.getDownloader(new URL("http://www.megaupload.com/?d=CVQKJ1KM"))
.download(new DownloadListener() {
@Override
public boolean timer(long time, TimerWaitReason reason) {
System.out.println("Waiting " + time + " in " + reason);
if (reason == TimerWaitReason.DOWNLOAD_TIMER)
return true;
public boolean timer(long time) {
System.out.println("Waiting " + time);
return false;
}
@Override
public String captcha(Captcha captcha) {
// TODO Auto-generated method stub
return null;
}
});
}
}