1
0
mirror of https://github.com/Rogiel/httpchannel synced 2025-12-06 07:32:50 +00:00

Implements 2shared service and improves channel link synchronization

This commit is contained in:
2012-01-22 21:58:01 -02:00
parent 3b06f0b9e6
commit cd835e2064
21 changed files with 440 additions and 25 deletions

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<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.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>httpchannel-service-2shared</artifactId>
<groupId>com.rogiel.httpchannel.service</groupId>
<name>HttpChannel/Service/TwoShared</name>
<description>Provides download and upload access for 2shared.com</description>
</project>

View File

@@ -0,0 +1,241 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.rogiel.httpchannel.service.twoshared;
import java.io.IOException;
import java.net.URI;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.regex.Pattern;
import com.rogiel.httpchannel.captcha.exception.UnsolvableCaptchaServiceException;
import com.rogiel.httpchannel.service.AbstractHttpDownloader;
import com.rogiel.httpchannel.service.AbstractHttpService;
import com.rogiel.httpchannel.service.AbstractUploader;
import com.rogiel.httpchannel.service.CapabilityMatrix;
import com.rogiel.httpchannel.service.DownloadChannel;
import com.rogiel.httpchannel.service.DownloadListener;
import com.rogiel.httpchannel.service.DownloadService;
import com.rogiel.httpchannel.service.Downloader;
import com.rogiel.httpchannel.service.DownloaderCapability;
import com.rogiel.httpchannel.service.Service;
import com.rogiel.httpchannel.service.ServiceID;
import com.rogiel.httpchannel.service.ServiceMode;
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.NullDownloaderConfiguration;
import com.rogiel.httpchannel.service.config.NullUploaderConfiguration;
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.NoCaptchaServiceException;
import com.rogiel.httpchannel.util.ExceptionUtils;
import com.rogiel.httpchannel.util.htmlparser.HTMLPage;
/**
* This service handles uploads to TwoShared.
*
* @author <a href="http://www.rogiel.com/">Rogiel</a>
* @since 1.0
*/
public class TwoSharedService extends AbstractHttpService implements Service,
UploadService<NullUploaderConfiguration>,
DownloadService<NullDownloaderConfiguration> {
/**
* This service ID
*/
public static final ServiceID SERVICE_ID = ServiceID.create("twoshared");
private static final Pattern UPLOAD_URL_PATTERN = Pattern
.compile("http://dc[0-9]*\\.2shared\\.com/main/upload2\\.jsp\\?sId=[A-z0-9]*");
private static final Pattern UPLOAD_ID_PATTERN = Pattern
.compile("sId=([A-z0-9]*)");
private static final Pattern DOWNLOAD_URL_PATTERN = Pattern
.compile("http://(www\\.)?2shared\\.com/document/[A-z0-9]*/.*");
private static final Pattern DIRECT_DOWNLOAD_URL_PATTERN = Pattern
.compile("http://dc[0-9]+\\.2shared\\.com/download/[A-z0-9]+/.+\\?tsid=[0-9]{8}-[0-9]{6}-[A-z0-9]{8}");
@Override
public ServiceID getServiceID() {
return SERVICE_ID;
}
@Override
public int getMajorVersion() {
return 1;
}
@Override
public int getMinorVersion() {
return 0;
}
@Override
public CapabilityMatrix<ServiceMode> getPossibleServiceModes() {
return new CapabilityMatrix<ServiceMode>(ServiceMode.UNAUTHENTICATED);
}
@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() {
// no configuration
return NullUploaderConfiguration.SHARED_INSTANCE;
}
@Override
public long getMaximumFilesize() {
// no filesize limit
return -1;
}
@Override
public String[] getSupportedExtensions() {
// no extension restriction
return null;
}
@Override
public CapabilityMatrix<UploaderCapability> getUploadCapabilities() {
return new CapabilityMatrix<UploaderCapability>(
UploaderCapability.UNAUTHENTICATED_UPLOAD);
}
@Override
public Downloader<NullDownloaderConfiguration> getDownloader(URI uri,
NullDownloaderConfiguration configuration) {
return new DownloaderImpl(uri, configuration);
}
@Override
public Downloader<NullDownloaderConfiguration> getDownloader(URI uri) {
return getDownloader(uri, newDownloaderConfiguration());
}
@Override
public NullDownloaderConfiguration newDownloaderConfiguration() {
return NullDownloaderConfiguration.SHARED_INSTANCE;
}
@Override
public boolean matchURI(URI uri) {
return DOWNLOAD_URL_PATTERN.matcher(uri.toString()).matches();
}
@Override
public CapabilityMatrix<DownloaderCapability> getDownloadCapabilities() {
return new CapabilityMatrix<DownloaderCapability>(
DownloaderCapability.UNAUTHENTICATED_DOWNLOAD,
DownloaderCapability.UNAUTHENTICATED_RESUME);
}
private class UploaderImpl extends
AbstractUploader<NullUploaderConfiguration> implements
Uploader<NullUploaderConfiguration>,
LinkedUploadChannelCloseCallback {
private Future<HTMLPage> uploadFuture;
private String uploadID;
public UploaderImpl(String filename, long filesize,
NullUploaderConfiguration configuration) {
super(TwoSharedService.this, filename, filesize, configuration);
}
@Override
public UploadChannel openChannel() throws IOException {
logger.debug("Starting upload to TwoShared");
final HTMLPage page = get("http://www.2shared.com/").asPage();
// locate upload uri
final String uri = page.findFormAction(UPLOAD_URL_PATTERN);
final String mainDC = page.getInputValue("mainDC");
uploadID = page.find(UPLOAD_ID_PATTERN, 1);
logger.debug("Upload URI: {}, DC: {}", uri, mainDC);
// create a new channel
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(uri).parameter("fff", channel)
.parameter("mainDC", mainDC).asPageAsync();
// wait for channel link
return waitChannelLink(channel);
}
@Override
public String finish() throws IOException {
try {
uploadFuture.get();
final HTMLPage page = get(
"http://www.2shared.com/uploadComplete.jsp?sId="
+ uploadID).asPage();
return page.getTextareaValueById("downloadLink");
} catch (InterruptedException e) {
return null;
} catch (ExecutionException e) {
ExceptionUtils.asIOException(e);
return null;
}
}
}
private class DownloaderImpl extends
AbstractHttpDownloader<NullDownloaderConfiguration> implements
Downloader<NullDownloaderConfiguration> {
/**
* @param uri
* the download uri
* @param configuration
* the downloader configuration
*/
protected DownloaderImpl(URI uri,
NullDownloaderConfiguration configuration) {
super(TwoSharedService.this, uri, configuration);
}
@Override
public DownloadChannel openChannel(DownloadListener listener,
long position) throws IOException,
DownloadLinkNotFoundException, DownloadLimitExceededException,
DownloadNotAuthorizedException, DownloadNotResumableException,
UnsolvableCaptchaServiceException, NoCaptchaServiceException {
final HTMLPage page = get(uri).asPage();
final String downloadUri = page.findScript(
DIRECT_DOWNLOAD_URL_PATTERN, 0);
return download(get(downloadUri));
}
}
}

View File

@@ -0,0 +1 @@
com.rogiel.httpchannel.service.twoshared.TwoSharedService

View File

@@ -0,0 +1,57 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.rogiel.httpchannel.service.twoshared;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import junit.framework.Assert;
import org.junit.Test;
import com.rogiel.httpchannel.service.Downloader;
import com.rogiel.httpchannel.util.ChannelUtils;
/**
* @author <a href="http://www.rogiel.com">Rogiel</a>
*
*/
public class TwoSharedServiceTest {
private final TwoSharedService service = new TwoSharedService();
@Test
public void testUpload() throws IOException {
final Path path = Paths
.get("../src/test/resources/upload-test-file.txt");
final URI uri = ChannelUtils.upload(service, path);
Assert.assertNotNull(uri);
System.out.println(uri);
}
@Test
public void testDownload() throws IOException {
final Downloader<?> downloader = service
.getDownloader(URI
.create("http://www.2shared.com/document/04tjgnAr/upload-test-file.html"));
System.out.println(new String(ChannelUtils.toByteArray(downloader.openChannel())));
}
}

View File

@@ -201,7 +201,7 @@ public class FourSharedService extends AbstractHttpService implements Service,
.parameter("FilePart", channel).asPageAsync();
// wait for channel link
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
} catch (ApiException e) {
throw new ChannelServiceException(e);
}

View File

@@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.httpchannel.service.fourshared;
import com.rogiel.httpchannel.service.AbstractUploaderConfiguration;
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 FourSharedUploaderConfiguration extends
AbstractUploaderConfiguration implements UploaderConfiguration,
DescriptionableUploaderConfiguration {
/**
* The upload description
*/
private String description = DescriptionableUploaderConfiguration.DEFAULT_DESCRIPTION;
@Override
public String description() {
return description;
}
@Override
public FourSharedUploaderConfiguration description(String description) {
this.description = description;
return this;
}
}

View File

@@ -135,7 +135,7 @@ public class ${serviceName}Service extends AbstractHttpService implements
uploadFuture = multipartPost(uri).parameter("[file-parameter]", channel).asPageAsync();
// wait for channel link
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
}
@Override

View File

@@ -183,7 +183,7 @@ public class DepositFilesService extends AbstractHttpService implements
.parameter("UPLOAD_IDENTIFIER", uploadID)
.parameter("agree", true)
.parameter("MAX_FILE_SIZE", maxFileSize).asPageAsync();
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
}
@Override

View File

@@ -174,7 +174,7 @@ public class FileSonicService extends AbstractHttpService implements Service,
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(api.getUploadURI().toString())
.parameter("files[]", channel).asStringAsync();
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
}
@Override

View File

@@ -220,7 +220,7 @@ public class HotFileService extends AbstractHttpService implements Service,
uploadFuture = multipartPost(action)
.parameter("uploads[]", channel).asPageAsync();
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
}
@Override

View File

@@ -232,7 +232,7 @@ public class MegaUploadService extends AbstractHttpService implements Service,
uploadFuture = multipartPost(uri)
.parameter("multimessage_0", configuration.description())
.parameter("multifile_0", channel).asStringAsync();
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
}
@Override

View File

@@ -239,7 +239,7 @@ public class MultiUploadService extends AbstractHttpService implements Service,
}
uploadFuture = request.asStringAsync();
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
}
@Override

View File

@@ -228,7 +228,7 @@ public class UploadHereService extends AbstractHttpService implements Service,
uploadFuture = multipartPost(uri).parameter("file_0", channel)
.parameter("u", userCookie)
.parameter("UPLOAD_IDENTIFIER", uploadID).asStringAsync();
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
}
@Override

View File

@@ -228,7 +228,7 @@ public class UploadKingService extends AbstractHttpService implements Service,
uploadFuture = multipartPost(uri).parameter("file", channel)
.parameter("u", userCookie)
.parameter("UPLOAD_IDENTIFIER", uploadID).asStringAsync();
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
}
@Override

View File

@@ -175,7 +175,7 @@ public class WUploadService extends AbstractHttpService implements Service,
final LinkedUploadChannel channel = createLinkedChannel(this);
uploadFuture = multipartPost(api.getUploadURI().toString())
.parameter("files[]", channel).asStringAsync();
return waitChannelLink(channel, uploadFuture);
return waitChannelLink(channel);
}
@Override

View File

@@ -202,7 +202,7 @@ public class ZShareService extends AbstractHttpService implements Service/*
// .parameter("descr", configuration.description())
// .parameter("TOS", true).parameter("is_private", false)
// .asStringAsync();
// return waitChannelLink(channel, uploadFuture);
// return waitChannelLink(channel);
// }
//
// @Override

View File

@@ -24,6 +24,7 @@
<module>httpchannel-service-wupload</module>
<module>httpchannel-service-zshare</module>
<module>httpchannel-service-4shared</module>
<module>httpchannel-service-2shared</module>
</modules>
<dependencies>