Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(opds): download a "sample" or "open access" publication behind an authwall #2732

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/common/redux/actions/import/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// ==LICENSE-BEGIN==
// Copyright 2017 European Digital Reading Lab. All rights reserved.
// Licensed to the Readium Foundation under one or more contributor license agreements.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file exposed on Github (readium) in the project repository.
// ==LICENSE-END==
// // ==LICENSE-BEGIN==
// // Copyright 2017 European Digital Reading Lab. All rights reserved.
// // Licensed to the Readium Foundation under one or more contributor license agreements.
// // Use of this source code is governed by a BSD-style license
// // that can be found in the LICENSE file exposed on Github (readium) in the project repository.
// // ==LICENSE-END==

import * as verify from "./verify";
// import * as verify from "./verify";

export {
verify,
};
// export {
// verify,
// };
54 changes: 27 additions & 27 deletions src/common/redux/actions/import/verify.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
// ==LICENSE-BEGIN==
// Copyright 2017 European Digital Reading Lab. All rights reserved.
// Licensed to the Readium Foundation under one or more contributor license agreements.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file exposed on Github (readium) in the project repository.
// ==LICENSE-END==
// // ==LICENSE-BEGIN==
// // Copyright 2017 European Digital Reading Lab. All rights reserved.
// // Licensed to the Readium Foundation under one or more contributor license agreements.
// // Use of this source code is governed by a BSD-style license
// // that can be found in the LICENSE file exposed on Github (readium) in the project repository.
// // ==LICENSE-END==

import { Action } from "readium-desktop/common/models/redux";
import { IOpdsLinkView, IOpdsPublicationView } from "readium-desktop/common/views/opds";
// import { Action } from "readium-desktop/common/models/redux";
// import { IOpdsLinkView, IOpdsPublicationView } from "readium-desktop/common/views/opds";

export const ID = "IMPORT_VERIFICATION_REQUEST";
// export const ID = "IMPORT_VERIFICATION_REQUEST";

export interface Payload {
link: IOpdsLinkView;
pub: IOpdsPublicationView;
}
// export interface Payload {
// link: IOpdsLinkView;
// pub: IOpdsPublicationView;
// }

export function build(
link: IOpdsLinkView,
pub: IOpdsPublicationView,
): Action<typeof ID, Payload> {
// export function build(
// link: IOpdsLinkView,
// pub: IOpdsPublicationView,
// ): Action<typeof ID, Payload> {

return {
type: ID,
payload: {
link,
pub,
},
};
}
build.toString = () => ID; // Redux StringableActionCreator
export type TAction = ReturnType<typeof build>;
// return {
// type: ID,
// payload: {
// link,
// pub,
// },
// };
// }
// build.toString = () => ID; // Redux StringableActionCreator
// export type TAction = ReturnType<typeof build>;
4 changes: 2 additions & 2 deletions src/common/redux/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as dialogActions from "./dialog/";
import * as downloadActions from "./download/";
import * as historyActions from "./history";
import * as i18nActions from "./i18n/";
import * as importActions from "./import/";
// import * as importActions from "./import/";
import * as keyboardActions from "./keyboard/";
import * as lcpActions from "./lcp/";
import * as loadActions from "./load";
Expand All @@ -37,7 +37,7 @@ export {
netActions,
readerActions,
lcpActions,
importActions,
// importActions,
toastActions,
downloadActions,
keyboardActions,
Expand Down
2 changes: 2 additions & 0 deletions src/main/redux/sagas/api/browser/browse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,8 @@ export function* browse(urlRaw: string): SagaGenerator<THttpGetBrowserResultView
}

// parse OPDS and return
// how to deal with the dowload of the publication ?
// no opds data will be returned
const dataFromOpdsParser = await opdsService.opdsRequestTransformer(data as IHttpGetResult<IOpdsResultView>);
if (dataFromOpdsParser) {
data.data = {
Expand Down
89 changes: 34 additions & 55 deletions src/main/services/opds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import { diSymbolTable } from "../diSymbolTable";
import { getOpdsAuthenticationChannel } from "../event";
import { OPDSLink } from "@r2-opds-js/opds/opds2/opds2-link";
import { IDigestDataParsed, parseDigestString } from "readium-desktop/utils/digest";
import { diMainGet } from "../di";
import { importFromLinkService } from "../redux/sagas/api/publication/import/importFromLink";

// Logger
const debug = debug_("readium-desktop:main#services/opds");
Expand Down Expand Up @@ -84,12 +86,11 @@ export class OpdsService {
contentType: _contentType,
} = httpGetData;
const baseUrl = `${_baseUrl}`;
const contentType = parseContentType(_contentType);
const contentType = parseContentType(_contentType);

if (contentTypeisXml(contentType)) {
if (contentTypeisXml(contentType)) {


// TODO response.buffer deprecated by node-fetch
// TODO: response.buffer deprecated by node-fetch
const buffer = await httpGetData.response.buffer();
const result = await this.opdsRequestXmlTransformer(buffer, baseUrl);

Expand Down Expand Up @@ -129,6 +130,33 @@ export class OpdsService {
}
}

// TODO:
// now sample and open access pub acquisition will be handled like an opds feed
// with a download fallback if it is not parsable to an opds format
// What it means that a misconfigured or rotten opds feed can download anything to the user disk
// I suggest a user confirmation dialog modal to accept the download of the target link if legit

// To implement this need to switch to redux saga to ask and wait response in saga mode

// For the moment let's user download without confirmation

const downloadLink: IOpdsLinkView = {
url: _baseUrl.toString(),
type: contentType,
};

const sagaMiddleware = diMainGet("saga-middleware");
sagaMiddleware.run(importFromLinkService, downloadLink);

// https://github.com/edrlab/thorium-reader/issues/1261
// publication in OPDS2 feed might be an OPDSPublication or an R2Publication
// now downloaded and packaged in importFromLinkService saga function !


// TODO: what return when the publication is not an opds feed, we have to close the current publication info and reload the previous history odps link !?!


// TODO: What return here, when we have to reload the history previous link instead !?!
return undefined;
}

Expand Down Expand Up @@ -239,14 +267,6 @@ export class OpdsService {
!jsonObj.groups &&
!jsonObj.catalogs);

const isR2Pub = contentType === ContentType.webpub ||
jsonObj.metadata &&
jsonObj["@context"] === "https://readium.org/webpub-manifest/context.jsonld" &&
!!(!jsonObj.publications &&
!jsonObj.navigation &&
!jsonObj.groups &&
!jsonObj.catalogs);

const isAuth = contentTypeisOpdsAuth(contentType) ||
typeof jsonObj.authentication !== "undefined";

Expand All @@ -256,7 +276,7 @@ export class OpdsService {
jsonObj.groups ||
jsonObj.catalogs);

debug("isAuth, isOpdsPub, isR2Pub, isFeed", isAuth, isOpdsPub, isR2Pub, isFeed);
debug("isAuth, isOpdsPub, isR2Pub, isFeed", isAuth, isOpdsPub, isFeed);
// debug(jsonObj);
// console.log(JSON.stringify(jsonObj, null, 4));
if (isAuth) {
Expand All @@ -283,47 +303,7 @@ export class OpdsService {
publications: [pubView],
};

} else if (isR2Pub) {

// TODO : https://github.com/edrlab/thorium-reader/issues/1261
// publication in OPDS2 feed might be an OPDSPublication or an R2Publication

debug("R2Publication in OPDS not supported");

// const r2Publication = TaJsonDeserialize(
// jsonObj,
// R2Publication,
// );

// const pub = new OPDSPublication();

// if (typeof r2Publication.Metadata === "object") {
// pub.Metadata = r2Publication.Metadata;
// }

// const coverLink = r2Publication.searchLinkByRel("cover");
// if (coverLink) {
// pub.AddImage(
// coverLink.Href,
// coverLink.TypeLink,
// coverLink.Height, coverLink.Width);
// }

// pub.AddLink_(, "application/webpub+json", "http://opds-spec.org/acquisition/open-access", "");

// const pubView = this.opdsFeedViewConverter.convertOpdsPublicationToView(r2Publication, baseUrl);

// return {
// title: pubView.documentTitle,
// publications: [pubView],
// } as IOpdsResultView;

return {
title: "",
publications: [],
};

} else if (isFeed) {
} else if (isFeed) {
const r2OpdsFeed = TaJsonDeserialize(
jsonObj,
OPDSFeed,
Expand All @@ -332,7 +312,6 @@ export class OpdsService {
}

return undefined;

}

private async opdsRequestXmlTransformer(buffer: Buffer, baseUrl: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import * as stylesGlobal from "readium-desktop/renderer/assets/styles/global.scs
import classNames from "classnames";
import * as React from "react";
import { connect } from "react-redux";
import { dialogActions, importActions } from "readium-desktop/common/redux/actions/";
// import { dialogActions, importActions } from "readium-desktop/common/redux/actions/";
import { IOpdsLinkView, IOpdsPublicationView } from "readium-desktop/common/views/opds";
import * as CartFillIcon from "readium-desktop/renderer/assets/icons/cart-icon.svg";
import * as BorrowIcon from "readium-desktop/renderer/assets/icons/borrow-icon.svg";
Expand Down Expand Up @@ -54,7 +54,7 @@ export class OpdsControls extends React.Component<IProps, undefined> {

const {
opdsPublicationView,
verifyImport,
// verifyImport,
openAccessButtonIsDisabled,
sampleButtonIsDisabled,
__,
Expand Down Expand Up @@ -103,9 +103,15 @@ export class OpdsControls extends React.Component<IProps, undefined> {
);
} else {

verifyImport(
// verifyImport(
// ln,
// opdsPublicationView,
// );

this.props.link(
ln,
opdsPublicationView,
this.props.location,
`${"open access book"} (${opdsPublicationView.documentTitle}))`,
);
}
}}
Expand Down Expand Up @@ -137,9 +143,15 @@ export class OpdsControls extends React.Component<IProps, undefined> {
);
} else {

verifyImport(
// verifyImport(
// ln,
// opdsPublicationView,
// );

this.props.link(
ln,
opdsPublicationView,
this.props.location,
`${"sample book"} (${opdsPublicationView.documentTitle}))`,
);
}
}}
Expand Down Expand Up @@ -295,10 +307,10 @@ export class OpdsControls extends React.Component<IProps, undefined> {

const mapDispatchToProps = (dispatch: TDispatch, _props: IBaseProps) => {
return {
verifyImport: (...data: Parameters<typeof importActions.verify.build>) => {
dispatch(dialogActions.closeRequest.build());
dispatch(importActions.verify.build(...data));
},
// verifyImport: (...data: Parameters<typeof importActions.verify.build>) => {
// dispatch(dialogActions.closeRequest.build());
// dispatch(importActions.verify.build(...data));
// },
link: (...data: Parameters<ReturnType<typeof dispatchOpdsLink>>) =>
dispatchOpdsLink(dispatch)(...data),
};
Expand Down
10 changes: 4 additions & 6 deletions src/renderer/library/opds/handleLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { IOpdsLinkView } from "readium-desktop/common/views/opds";
import { decodeB64 } from "readium-desktop/renderer/common/logics/base64";
import { buildOpdsBrowserRoute } from "readium-desktop/renderer/library/opds/route";
import { TDispatch } from "readium-desktop/typings/redux";
import { ContentType, parseContentType } from "readium-desktop/utils/contentType";
import { parseContentType } from "readium-desktop/utils/contentType";

import { Location } from "history";

Expand All @@ -29,12 +29,10 @@ export const dispatchOpdsLink =
dispatch(dialogActions.closeRequest.build());

const contentType = parseContentType(ln.type);
if (contentType === ContentType.Opds2 ||
contentType === ContentType.Opds2Auth ||
contentType === ContentType.Opds2Pub ||
contentType === ContentType.AtomXml ||
if (
contentType ||
REL_NAVIGATION_TYPES.includes(ln.rel)
) {
) {

const param = extractParamFromOpdsRoutePathname(location.pathname);

Expand Down
4 changes: 2 additions & 2 deletions src/renderer/library/redux/sagas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import * as i18n from "./i18n";
import * as lcp from "./lcp";
import * as load from "./load";
import * as opds from "./opds";
import * as sameFileImport from "./sameFileImport";
// import * as sameFileImport from "./sameFileImport";
import * as winInit from "./win";

// Logger
Expand All @@ -45,7 +45,7 @@ export function* rootSaga() {

publicationInfoReaderAndLib.saga(),

sameFileImport.saga(),
// sameFileImport.saga(),
history.saga(),
publicationInfoSyncTags.saga(),

Expand Down
Loading
Loading