Nervige C&P-Sperren umgehen

Novgorod

ngb-Nutte
Registriert
14 Juli 2013
Beiträge
3.055
Servus,

in vielen web-formularen gibts ja schon länger die unsitte, dass bei bestätigungsfeldern (insbesondere email-adressen) copy&paste per javascript gesperrt ist, damit man es ja von hand tippt.. über den sinn und unsinn dessen will ich hier auch garnicht diskutieren (wer herausgefunden hat wie c&p funktioniert, kriegt es vielleicht gerade noch hin, seine email-adresse korrekt einzutragen, aber mei), sondern wie man das am einfachsten bekämpft.. javascript temporär zu deaktivieren ist dafür in 99% der fälle ungeeignet, da dann meist das submitten nicht mehr geht und das formular neugeladen wird, wobei alle felder gelöscht werden (letzterem kann man mit dem lazarus-addon für firefox o.ä. entgegenwirken, ist aber umständlich)..

am elegantesten wäre eine art selektive abschaltung aller javascript-funktionen, die sich auf eingaben auswirken (es gab ja beispielsweise vor vielen jahren mal den brauch, den rechtsklick per javascript zu "sperren" um das speichern von bildern zu verhindern -> lol), ohne die seite vom server neu zu laden und formulardaten zu löschen (geht sowas evtl. mit noscript?).. möglicherweise wird dadurch auch das submitten unmöglich (wenn das über "onklick" o.ä. läuft), aber dann kann man vor dem submitten diesen "safe-mode" einfach wieder abschalten.. alternativ ginge es auch browserunabhängig mit einem c&p-tool, das tastatureingaben emuliert (makro/hotkey-funktion).. was ist der beste weg?
 
Ein einfachsten wäre es vermutlich, einfach alle [kw]onkeydown[/kw]-, [kw]onkeyup[/kw]-, [kw]onkeypress[/kw]-Eventlistener für Textfelder und Textareas zu löschen. Das ist sicher sogar per Userscript möglich. Wenn Du mal eine Seite verlinken kannst, bei man das testen kann, kann gerne mal ausprobieren, ob ich das auf die Schnelle hinkriege.
 
  • Thread Starter Thread Starter
  • #3
spontan fällt mir die bahnticket-buchung ein (ich hoffe der link funktioniert ohne session-cookies):

 
Da du offenbar Firefox nutzt, hast du schon mal probiert den Text im ersten E-Mail Feld zu markieren und via Drag&Drop in das Email-Bestätigen Feld zu ziehen?
 
Ich hab's jetzt erst mal nur mit Chrome und Tampermonkey getestet. Damit kannst Du die Event-Listener mithilfe eines Userscripts löschen:

[src=javascript]// ==UserScript==
// @name Entferne C&P-Sperre für Bahnbuchung.de
// @version 0.1
// @match https://bahnbuchung.de/*
// ==/UserScript==

var el = document.getElementById('EmailValidate');
var elClone = el.cloneNode(true);
elClone.removeAttribute('onpaste');
elClone.removeAttribute('id');

el.parentNode.replaceChild(elClone, el);[/src]

Nicht vergessen, in den Einstellungen des User-Scripts die Option "Nur im Haupt-Frame ausführen" auf "Nein" zu stellen.
 
  • Thread Starter Thread Starter
  • #6
super :T

aber kann man das noch allgemeingültiger machen? im quelltext heißt es ja:
[src=html4strict]<input onpaste="..." ...>[/src]

also gehts (simpler als erwartet) über das "onpaste"-attribut.. da ich mir keinen sinnvollen zweck dieser abfrage vorstellen kann, würde ich dieses attribut eben generell auf allen webseiten löschen (und falls es doch mal sinnvoll sein sollte, kann man ja das userscript kurz deaktivieren).. wie sähe so ein script aus, das prinzipiell bei jedem <input> element das onpaste-attribut entfernt?
 
Klar geht das auch allgemeiner, du musst lediglich aus der spezifischen eine allgemeinere Suche machen..

[src=javascript]var el = document.getElementById('EmailValidate');[/src]

Statt nach genau diesem speziellen Feld zu suchen, kannst du natürlich auch sämtliche input-Knoten suchen, deren onpaste-Attribut nicht null (leer / ungesetzt) ist.
Allerdings reicht es, genau auf der angegebenen Beispielseite nicht aus, nur das onpaste-Attribut zu entfernen. Da wird ebenfalls eine Abfrage über die ID realisiert. Also muss in genau diesem Fall eben auch die ID entfernt werden.


[src=javascript]
var dropEvilOnPasteAttribute = function () {
var c = 0;
var log = "";

/* only search for input fields */
var inputs = document.getElementsByTagName('input');

// return, if non were found
if(inputs.length==0){ return 'no input found'; }

/* check all input fields */
for(var i=0; i<inputs.length; i++) {
// write log
log += "element "+inputs.getAttribute('name') + ' will be checked';

// onpast is at least set
if(inputs.getAttribute('onpaste') != null) {
// drop onpaste, id but mark that field as pastable
inputs.setAttribute('onpaste', "");
inputs.setAttribute('placeholder', inputs.getAttribute('value') + " (pastable)");
inputs.setAttribute('id', "");
// also write log
log += " found and removed the evil onpaste attribute";
} else {
// nothing to do here, but write log
log += " there seems to be no evil inside";
}
// each entry should get it's own line, windows
log += "\n\r";
}
// we're done
return log;
};

var evilshitremoved = dropEvilOnPasteAttribute();
// debug
//alert(evilshitremoved);
[/src]

Wie bereits erwähnt:

Starte wenn: document-end
Nur im Hauptframe ausführen: nein

Für deine spezielle Seite:
// @match
// @match

Bzw. unter Match



Zum Debuggen einfach in der letzten Zeile die Slashes entfernen..
 
  • Thread Starter Thread Starter
  • #8
ok, cool, danke für die ausführliche aufklärung! :T

achja, warum tust du da noch das attribut "placeholder" mit rein, was als wert offenbar den default-wert des input-feldes ("value"-attribut) mit " (pastable)" angehängt bekommt? :confused:
 
Dabei vergisst Du aber die Event-Listener. Wenn ich den Event-Listener beispielsweise per [kw]element.addEventListener('paste', function(){ ... })[/kw] erzeuge, reagiert Dein Script nicht darauf. Daher hab ich in meinem Beispiel einfach eine Kopie vom Event gemacht. Die ID hab ich sicherheitshalber gelöscht, falls die Seite auf die Idee kommt, den Event-Listener nachträglich über die ID nochmal hinzuzufügen.
 
Könntet ihr mal verifizieren ob das folgende Snippet auf den betreffenden Seiten funktioniert?

[src=javascript]document.addEventListener('paste', function(e){
e.stopImmediatePropagation();
}, true);[/src]

In meinen Tests unterdrückt es alle nachfolgenden Event-Handler für das paste-Event, egal ob über das onpaste-Attribut oder addEventListener definiert. Das Snippet muss ebenfalls vor allen anderen Scripts ausgeführt werden.
 
Das wird schwierig, denn das Bahnbuchung-Script nutzt ebenfalls irgendeinen onReady-Handler, um die Event-Listener zu setzen. Man wird es also über ein User-Script vermutlich nicht schaffen, den Augenblick zwischen Geburt vom Input-Feld und Start des Event-Handlers abzupassen, um dann seinen eigenen Event-Listener dazwischen zu schieben.

Die betreiben einen relativ hohen Aufwand, um das zu verhindern. Falls onpaste nicht funktioniert, fragen die auch noch ab, ob STRG+V gedrückt wurde:

[src=javascript]window.ctrlDown = false;
function handleKeyDown(event) {
if(event.keyCode===224||event.keyCode===91||event.keyCode===17){
window.ctrlDown = true;
}
if(event.keyCode===86 && window.ctrlDown) {
event.preventDefault();
event.stopPropagation();
showEmailNoCopyNotice();
}
}

function handleKeyUp(event) {
if (event.keyCode===224||event.keyCode===91||event.keyCode===17){
window.ctrlDown = false;
}
}

function showEmailNoCopyNotice() {
showTip('EmailValidate', 'emailNoCopyTip', null, null, null, null, false);
window.setTimeout(function(){
hideTip('emailNoCopyTip');
}, 5000);
}

Ext.onReady(function() {
var validate = document.getElementById('EmailValidate');
if (validate.addEventListener) {
validate.addEventListener('keydown', handleKeyDown, true);
validate.addEventListener('keypress', handleKeyDown, true);
validate.addEventListener('keyup', handleKeyUp, true);
} else {
validate.attachEvent('keydown', handleKeyDown);
validate.attachEvent('keypress', handleKeyDown);
validate.attachEvent('keyup', handleKeyUp);
}
});[/src]
 
Nicht mit mir - nicht mit'm Commander!

Folgenden Code hab ich nun mit GreaseMonkey getestet, sollte funktionieren:

[src=javascript]
// ==UserScript==
// @name Stop-OnPaste
// @version 1
// @grant none
// ==/UserScript==

Object.defineProperty(window, 'ctrlDown', { get: function(){
return false;
}});

document.addEventListener('paste', function(e){
e.stopImmediatePropagation();
}, true);
[/src]

Der ergänzte Code-Teil sorgt dafür, dass deren globale Variable ctrlDown nicht durch einfache Zuweisung überschrieben werden kann und immer false zurückliefert – So wird die Abfrage nach Strg+V, wie sie im betreffenden Script definiert ist, nie erfolgreich sein.
 
achja, warum tust du da noch das attribut "placeholder" mit rein, was als wert offenbar den default-wert des input-feldes ("value"-attribut) mit " (pastable)" angehängt bekommt? :confused:
Den placeholder habe ich rein gemacht, dass man erkennt, wenn ein Feld modifiziert wurde. Dass das bei gesetztem value natürlich nicht mehr sichtbar ist.. schau mal auf die Uhrzeit. ;)

Dabei vergisst Du aber die Event-Listener. Wenn ich den Event-Listener beispielsweise per [kw]element.addEventListener('paste', function(){ ... })[/kw] erzeuge, reagiert Dein Script nicht darauf. Daher hab ich in meinem Beispiel einfach eine Kopie vom Event gemacht. Die ID hab ich sicherheitshalber gelöscht, falls die Seite auf die Idee kommt, den Event-Listener nachträglich über die ID nochmal hinzuzufügen.
Es war 4 Uhr, da vergesse ich so einiges, insbesondere die prinzipielle Existenz von Event-Listenern ;)

@sars, deine Lösung gefällt mir, aber bist du sicher, dass das nicht auch Seiteneffekte haben kann?
 
  • Thread Starter Thread Starter
  • #15
perfekt! seiteneffekte dürfte es höchstens in irgendwelchen browserspielchen geben und alles andere im web gehen meine tastatureingaben nichts an, fertig.. (außerdem kann man es ja mit 2 klicks deaktivieren, falls man sowas fürchtet)..
 
Zurück
Oben