Kaydet (Commit) 18fbddcc authored tarafından Pranav Kant's avatar Pranav Kant Kaydeden (comit) Caolán McNamara

lokdocview: Handle password protected documents

Change-Id: I606a1112c8eb4c1cc4596d6947ce1223543cc87c
Reviewed-on: https://gerrit.libreoffice.org/21861Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarCaolán McNamara <caolanm@redhat.com>
Tested-by: 's avatarCaolán McNamara <caolanm@redhat.com>
üst 59aee037
...@@ -285,6 +285,18 @@ gboolean lok_doc_view_paste (LOKDocView* ...@@ -285,6 +285,18 @@ gboolean lok_doc_view_paste (LOKDocView*
const gchar* pData, const gchar* pData,
gsize nSize); gsize nSize);
/**
* lok_doc_view_set_document_password:
* @pDocView: The #LOKDocView instance
* @pUrl: the URL of the document to set password for, as sent with signal `password-required`
* @pPassword: (nullable): the password, NULL for no password
*
* Set the password for password protected documents
*/
void lok_doc_view_set_document_password (LOKDocView* pDocView,
const gchar* pURL,
const gchar* pPassword);
/** /**
* lok_doc_view_pixel_to_twip: * lok_doc_view_pixel_to_twip:
* @pDocView: The #LOKDocView instance * @pDocView: The #LOKDocView instance
......
...@@ -486,10 +486,20 @@ static void toggleFindbar(GtkWidget* pButton, gpointer /*pItem*/) ...@@ -486,10 +486,20 @@ static void toggleFindbar(GtkWidget* pButton, gpointer /*pItem*/)
} }
} }
static void
setLOKFeatures (GtkWidget* pDocView)
{
g_object_set(G_OBJECT(pDocView),
"doc-password", TRUE,
"doc-password-to-modify", TRUE,
nullptr);
}
/// Common initialization, regardless if it's just a new view or a full init. /// Common initialization, regardless if it's just a new view or a full init.
static TiledWindow& setupWidgetAndCreateWindow(GtkWidget* pDocView) static TiledWindow& setupWidgetAndCreateWindow(GtkWidget* pDocView)
{ {
setupDocView(pDocView); setupDocView(pDocView);
setLOKFeatures(pDocView);
TiledWindow aWindow; TiledWindow aWindow;
aWindow.m_pDocView = pDocView; aWindow.m_pDocView = pDocView;
GtkWidget* pWindow = createWindow(aWindow); GtkWidget* pWindow = createWindow(aWindow);
...@@ -861,6 +871,45 @@ static void formulaChanged(LOKDocView* pLOKDocView, char* pPayload, gpointer /*p ...@@ -861,6 +871,45 @@ static void formulaChanged(LOKDocView* pLOKDocView, char* pPayload, gpointer /*p
gtk_entry_set_text(GTK_ENTRY(rWindow.m_pFormulabarEntry), pPayload); gtk_entry_set_text(GTK_ENTRY(rWindow.m_pFormulabarEntry), pPayload);
} }
/// LOKDocView password is requried to open the document
static void passwordRequired(LOKDocView* pLOKDocView, gchar* pUrl, gboolean bModify, gpointer /*pData*/)
{
GtkWidget* pPasswordDialog = gtk_dialog_new_with_buttons ("Password required",
GTK_WINDOW (gtk_widget_get_toplevel(GTK_WIDGET(pLOKDocView))),
GTK_DIALOG_MODAL,
"OK",
GTK_RESPONSE_OK,
nullptr);
g_object_set(G_OBJECT(pPasswordDialog), "resizable", FALSE, nullptr);
GtkWidget* pDialogMessageArea = gtk_dialog_get_content_area (GTK_DIALOG (pPasswordDialog));
GtkWidget* pPasswordEntry = gtk_entry_new ();
gtk_entry_set_visibility (GTK_ENTRY(pPasswordEntry), FALSE);
gtk_entry_set_invisible_char (GTK_ENTRY(pPasswordEntry), '*');
gtk_box_pack_end(GTK_BOX(pDialogMessageArea), pPasswordEntry, TRUE, TRUE, 2);
if (bModify)
{
GtkWidget* pSecondaryLabel = gtk_label_new ("Document requires password to edit");
gtk_box_pack_end(GTK_BOX(pDialogMessageArea), pSecondaryLabel, TRUE, TRUE, 2);
gtk_dialog_add_button (GTK_DIALOG (pPasswordDialog), "Open as read-only", GTK_RESPONSE_ACCEPT);
}
gtk_widget_show_all(pPasswordDialog);
gint res = gtk_dialog_run (GTK_DIALOG(pPasswordDialog));
switch (res)
{
case GTK_RESPONSE_OK:
lok_doc_view_set_document_password (pLOKDocView, pUrl, gtk_entry_get_text(GTK_ENTRY(pPasswordEntry)));
break;
case GTK_RESPONSE_ACCEPT:
// User accepts to open this document as read-only
case GTK_RESPONSE_DELETE_EVENT:
lok_doc_view_set_document_password (pLOKDocView, pUrl, nullptr);
break;
}
gtk_widget_destroy(pPasswordDialog);
}
static void toggleToolItem(GtkWidget* pWidget, gpointer /*pData*/) static void toggleToolItem(GtkWidget* pWidget, gpointer /*pData*/)
{ {
TiledWindow& rWindow = lcl_getTiledWindow(pWidget); TiledWindow& rWindow = lcl_getTiledWindow(pWidget);
...@@ -1353,6 +1402,7 @@ static void setupDocView(GtkWidget* pDocView) ...@@ -1353,6 +1402,7 @@ static void setupDocView(GtkWidget* pDocView)
g_signal_connect(pDocView, "hyperlink-clicked", G_CALLBACK(signalHyperlink), nullptr); g_signal_connect(pDocView, "hyperlink-clicked", G_CALLBACK(signalHyperlink), nullptr);
g_signal_connect(pDocView, "cursor-changed", G_CALLBACK(cursorChanged), nullptr); g_signal_connect(pDocView, "cursor-changed", G_CALLBACK(cursorChanged), nullptr);
g_signal_connect(pDocView, "formula-changed", G_CALLBACK(formulaChanged), nullptr); g_signal_connect(pDocView, "formula-changed", G_CALLBACK(formulaChanged), nullptr);
g_signal_connect(pDocView, "password-required", G_CALLBACK(passwordRequired), nullptr);
} }
int main( int argc, char* argv[] ) int main( int argc, char* argv[] )
......
...@@ -65,6 +65,8 @@ struct LOKDocViewPrivateImpl ...@@ -65,6 +65,8 @@ struct LOKDocViewPrivateImpl
glong m_nDocumentHeightTwips; glong m_nDocumentHeightTwips;
/// View or edit mode. /// View or edit mode.
gboolean m_bEdit; gboolean m_bEdit;
/// LOK Features
guint64 m_nLOKFeatures;
/// Position and size of the visible cursor. /// Position and size of the visible cursor.
GdkRectangle m_aVisibleCursor; GdkRectangle m_aVisibleCursor;
/// Cursor overlay is visible or hidden (for blinking). /// Cursor overlay is visible or hidden (for blinking).
...@@ -147,6 +149,7 @@ struct LOKDocViewPrivateImpl ...@@ -147,6 +149,7 @@ struct LOKDocViewPrivateImpl
m_nDocumentWidthTwips(0), m_nDocumentWidthTwips(0),
m_nDocumentHeightTwips(0), m_nDocumentHeightTwips(0),
m_bEdit(FALSE), m_bEdit(FALSE),
m_nLOKFeatures(0),
m_aVisibleCursor({0, 0, 0, 0}), m_aVisibleCursor({0, 0, 0, 0}),
m_bCursorOverlayVisible(false), m_bCursorOverlayVisible(false),
m_bCursorVisible(true), m_bCursorVisible(true),
...@@ -204,6 +207,7 @@ enum ...@@ -204,6 +207,7 @@ enum
COMMAND_RESULT, COMMAND_RESULT,
FORMULA_CHANGED, FORMULA_CHANGED,
TEXT_SELECTION, TEXT_SELECTION,
PASSWORD_REQUIRED,
LAST_SIGNAL LAST_SIGNAL
}; };
...@@ -224,6 +228,8 @@ enum ...@@ -224,6 +228,8 @@ enum
PROP_DOC_HEIGHT, PROP_DOC_HEIGHT,
PROP_CAN_ZOOM_IN, PROP_CAN_ZOOM_IN,
PROP_CAN_ZOOM_OUT, PROP_CAN_ZOOM_OUT,
PROP_DOC_PASSWORD,
PROP_DOC_PASSWORD_TO_MODIFY,
PROP_LAST PROP_LAST
}; };
...@@ -323,6 +329,10 @@ callbackTypeToString (int nType) ...@@ -323,6 +329,10 @@ callbackTypeToString (int nType)
return "LOK_CALLBACK_SET_PART"; return "LOK_CALLBACK_SET_PART";
case LOK_CALLBACK_SEARCH_RESULT_SELECTION: case LOK_CALLBACK_SEARCH_RESULT_SELECTION:
return "LOK_CALLBACK_SEARCH_RESULT_SELECTION"; return "LOK_CALLBACK_SEARCH_RESULT_SELECTION";
case LOK_CALLBACK_DOCUMENT_PASSWORD:
return "LOK_CALLBACK_DOCUMENT_PASSWORD";
case LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY:
return "LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY";
} }
return nullptr; return nullptr;
} }
...@@ -831,6 +841,7 @@ globalCallback (gpointer pData) ...@@ -831,6 +841,7 @@ globalCallback (gpointer pData)
{ {
CallbackData* pCallback = static_cast<CallbackData*>(pData); CallbackData* pCallback = static_cast<CallbackData*>(pData);
LOKDocViewPrivate& priv = getPrivate(pCallback->m_pDocView); LOKDocViewPrivate& priv = getPrivate(pCallback->m_pDocView);
gboolean bModify = false;
switch (pCallback->m_nType) switch (pCallback->m_nType)
{ {
...@@ -852,12 +863,12 @@ globalCallback (gpointer pData) ...@@ -852,12 +863,12 @@ globalCallback (gpointer pData)
g_signal_emit (pCallback->m_pDocView, doc_view_signals[LOAD_CHANGED], 0, 1.0); g_signal_emit (pCallback->m_pDocView, doc_view_signals[LOAD_CHANGED], 0, 1.0);
} }
break; break;
case LOK_CALLBACK_DOCUMENT_PASSWORD:
case LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY: case LOK_CALLBACK_DOCUMENT_PASSWORD_TO_MODIFY:
bModify = true;
case LOK_CALLBACK_DOCUMENT_PASSWORD:
{ {
char const*const pURL(pCallback->m_aPayload.c_str()); char const*const pURL(pCallback->m_aPayload.c_str());
// TODO maybe allow more passwords g_signal_emit (pCallback->m_pDocView, doc_view_signals[PASSWORD_REQUIRED], 0, pURL, bModify);
priv->m_pOffice->pClass->setDocumentPassword(priv->m_pOffice, pURL, "1");
} }
break; break;
default: default:
...@@ -1960,6 +1971,8 @@ static void lok_doc_view_set_property (GObject* object, guint propId, const GVal ...@@ -1960,6 +1971,8 @@ static void lok_doc_view_set_property (GObject* object, guint propId, const GVal
{ {
LOKDocView* pDocView = LOK_DOC_VIEW (object); LOKDocView* pDocView = LOK_DOC_VIEW (object);
LOKDocViewPrivate& priv = getPrivate(pDocView); LOKDocViewPrivate& priv = getPrivate(pDocView);
gboolean bDocPasswordEnabled = priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD;
gboolean bDocPasswordToModifyEnabled = priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY;
switch (propId) switch (propId)
{ {
...@@ -1987,6 +2000,20 @@ static void lok_doc_view_set_property (GObject* object, guint propId, const GVal ...@@ -1987,6 +2000,20 @@ static void lok_doc_view_set_property (GObject* object, guint propId, const GVal
case PROP_DOC_HEIGHT: case PROP_DOC_HEIGHT:
priv->m_nDocumentHeightTwips = g_value_get_long (value); priv->m_nDocumentHeightTwips = g_value_get_long (value);
break; break;
case PROP_DOC_PASSWORD:
if (g_value_get_boolean (value) != bDocPasswordEnabled)
{
priv->m_nLOKFeatures = priv->m_nLOKFeatures ^ LOK_FEATURE_DOCUMENT_PASSWORD;
priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, priv->m_nLOKFeatures);
}
break;
case PROP_DOC_PASSWORD_TO_MODIFY:
if ( g_value_get_boolean (value) != bDocPasswordToModifyEnabled)
{
priv->m_nLOKFeatures = priv->m_nLOKFeatures ^ LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY;
priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, priv->m_nLOKFeatures);
}
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
} }
...@@ -2035,6 +2062,12 @@ static void lok_doc_view_get_property (GObject* object, guint propId, GValue *va ...@@ -2035,6 +2062,12 @@ static void lok_doc_view_get_property (GObject* object, guint propId, GValue *va
case PROP_CAN_ZOOM_OUT: case PROP_CAN_ZOOM_OUT:
g_value_set_boolean (value, priv->m_bCanZoomOut); g_value_set_boolean (value, priv->m_bCanZoomOut);
break; break;
case PROP_DOC_PASSWORD:
g_value_set_boolean (value, priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD);
break;
case PROP_DOC_PASSWORD_TO_MODIFY:
g_value_set_boolean (value, priv->m_nLOKFeatures & LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, propId, pspec);
} }
...@@ -2084,8 +2117,6 @@ static gboolean lok_doc_view_initable_init (GInitable *initable, GCancellable* / ...@@ -2084,8 +2117,6 @@ static gboolean lok_doc_view_initable_init (GInitable *initable, GCancellable* /
return FALSE; return FALSE;
} }
// priv->m_pOffice->pClass->setOptionalFeatures(priv->m_pOffice, LOK_FEATURE_DOCUMENT_PASSWORD|LOK_FEATURE_DOCUMENT_PASSWORD_TO_MODIFY);
return TRUE; return TRUE;
} }
...@@ -2273,6 +2304,33 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass) ...@@ -2273,6 +2304,33 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass)
static_cast<GParamFlags>(G_PARAM_READABLE static_cast<GParamFlags>(G_PARAM_READABLE
| G_PARAM_STATIC_STRINGS)); | G_PARAM_STATIC_STRINGS));
/**
* LOKDocView:doc-password:
*
* Set it to true if client supports providing password for viewing
* password protected documents
*/
properties[PROP_DOC_PASSWORD] =
g_param_spec_boolean("doc-password",
"Document password capability",
"Whether client supports providing document passwords",
FALSE,
static_cast<GParamFlags>(G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS));
/**
* LOKDocView:doc-password-to-modify:
*
* Set it to true if client supports providing password for edit-protected documents
*/
properties[PROP_DOC_PASSWORD_TO_MODIFY] =
g_param_spec_boolean("doc-password-to-modify",
"Edit document password capability",
"Whether the client supports providing passwords to edit documents",
FALSE,
static_cast<GParamFlags>(G_PARAM_READWRITE
| G_PARAM_STATIC_STRINGS));
g_object_class_install_properties(pGObjectClass, PROP_LAST, properties); g_object_class_install_properties(pGObjectClass, PROP_LAST, properties);
/** /**
...@@ -2459,6 +2517,37 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass) ...@@ -2459,6 +2517,37 @@ static void lok_doc_view_class_init (LOKDocViewClass* pClass)
g_cclosure_marshal_VOID__BOOLEAN, g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1, G_TYPE_NONE, 1,
G_TYPE_BOOLEAN); G_TYPE_BOOLEAN);
/**
* LOKDocView::password-required:
* @pDocView: the #LOKDocView on which the signal is emitted
* @pUrl: URL of the document for which password is required
* @bModify: whether password id required to modify the document
* This is true when password is required to edit the document,
* while it can still be viewed without password. In such cases, provide a NULL
* password for read-only access to the document.
* If false, password is required for opening the document, and document
* cannot be opened without providing a valid password.
*
* Password must be provided by calling lok_doc_view_set_document_password
* function with pUrl as provided by the callback.
*
* Upon entering a invalid password, another `password-required` signal is
* emitted.
* Upon entering a valid password, document starts to load.
* Upon entering a NULL password: if bModify is %TRUE, document starts to
* open in view-only mode, else loading of document is aborted.
*/
doc_view_signals[PASSWORD_REQUIRED] =
g_signal_new("password-required",
G_TYPE_FROM_CLASS(pGObjectClass),
G_SIGNAL_RUN_FIRST,
0,
nullptr, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 2,
G_TYPE_STRING,
G_TYPE_BOOLEAN);
} }
SAL_DLLPUBLIC_EXPORT GtkWidget* SAL_DLLPUBLIC_EXPORT GtkWidget*
...@@ -2859,6 +2948,16 @@ lok_doc_view_paste (LOKDocView* pDocView, ...@@ -2859,6 +2948,16 @@ lok_doc_view_paste (LOKDocView* pDocView,
return ret; return ret;
} }
SAL_DLLPUBLIC_EXPORT void
lok_doc_view_set_document_password (LOKDocView* pDocView,
const gchar* pURL,
const gchar* pPassword)
{
LOKDocViewPrivate& priv = getPrivate(pDocView);
priv->m_pOffice->pClass->setDocumentPassword(priv->m_pOffice, pURL, pPassword);
}
SAL_DLLPUBLIC_EXPORT gfloat SAL_DLLPUBLIC_EXPORT gfloat
lok_doc_view_pixel_to_twip (LOKDocView* pDocView, float fInput) lok_doc_view_pixel_to_twip (LOKDocView* pDocView, float fInput)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment