אינטרנט ישראל
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
  • ראשי
  • אודות רן בר-זיק ואינטרנט ישראל
  • ערוץ טלגרם
  • מסטודון
  • התחברו אלי בטוויטר
  • התחברו אלי בלינקדאין
  • ספר ג'אווהסקריפט
ראשי » פיתוח אינטרנט » פיתוח ב-JavaScript » Clipboard API

Clipboard API

רן בר-זיק יוני 30, 2020 6:24 pm 3 תגובות

הסקריפטים שלכם יכולים לשנות את ה-clipboard בקלות בדרך מודרנית, אסינכרונית ופשוטה – או באמצעות API או באמצעות אירועים.

כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.

אני מאמין שכל מי שקורא את השורות האלו מכיר את ה-Clipboard. מדובר בזכרון קטן שיכול להכיל תמונות וטקסטים והוא קיים בכל מערכת הפעלה שהיא. כמתכנתי אתרי אינטרנט אנחנו יכולים להתערב לא מעט במה שהמשתמש מעתיק ואפילו לקרוא את התוכן (לאחר קבלת הרשאה מהמשתמש). והכל עם ג'אווהסקריפט פשוט ביותר שעובד בכל הדפדפנים חוץ מאקספלורר.

עד לא מזמן, עבדנו עם document.execCommand כדי לעשות את זה. אבל בקרוב גם כרום וגם פיירפוקס יחסמו את document.execCommand – זה הזמן לגלות את Clipboard API! וגם לגלות כל מיני סכנות אבטחה מאוד מגניבות שבאות איתו.

אז ראשית, ל-Clipboard API הבסיסי:

כתיבה וקריאת מידע מה-Clipboard

הכנסת המידע היא פשוטה ביותר ונעשית באמצעות navigator.clipboard. בהוצאת המידע אנו נדרשים לבצע בדיקת הרשאות בדומה לפיצ'רים אחרים.

קודם כל – דוגמה קטנה שעובדת גם להעתקה וגם להדבקה. שימו לב שכשתדביקו – אתם תקבלו בקשה מהאתר לגישה למידע הזה.

הקוד נראה כך:

<div>
    <input type="text" class="to-copy" placeholder="כתבו פה משהו">
    <button class="write-button">העתיקו</button>
  </div>

  <div>
    <h3 class="clipboard-results"></h3>
    <button class="read-button">הדביקו</button>
  </div>
  <script>
const readButton = document.querySelector('.read-button');
const writeButton = document.querySelector('.write-button');

const resultsElement = document.querySelector('.clipboard-results');
const inputEl = document.querySelector('.to-copy');

const readHandler = async () => {
  try {
    const text = await navigator.clipboard.readText();
    resultsElement.innerText = text;
  } catch(e) {
    console.log('Error', e);
  }
};

readButton.addEventListener('click', readHandler);

const writeHandler = async () => {
  const inputValue = inputEl.value.trim() || '';
  try {
    await navigator.clipboard.writeText(inputValue);
    // The below code is just a UI indication
    const buttonText = 'הועתק, נסו להדביק';
    const originalText = writeButton.innerText;
    writeButton.innerText = buttonText;
    setTimeout(() => {
      writeButton.innerText = originalText;
    }, 2000);
  } catch(e) {
    console.log('Error', e);
  }
}

writeButton.addEventListener('click', writeHandler);
  </script>

הקוד הזה מדבר בעד עצמו אבל בואו נעשה סריקה מהירה. יש כאן שני כפתורים שהצמדתי אירוע לכל אחד מהם. אחד לקריאה (כלומר לקרוא מה שיש ב-Clipboard) והשני הוא כתיבה (כלומר לכתוב ב-Clipboard).

כתיבה

הכתיבה – כלומר למחוק (בלי לראות) את כל מה שיש ב-clipboard, לזרוק אותו ולשים שם את מה אנחנו רוצים זה פשוט. אם אני רוצה לכתוב טקסט, אני משתמש במתודת writeText. זו מתודה שמחזירה פרומיס:

navigator.clipboard.writeText(inputValue);

אין פה יותר מדי כאב ראש בטקסט. אבל המתודה הזו היא writeText. אם אנו רוצים לבצע העתקה של כל דבר אחר, זה מעט יותר מסובך ואנו צריכים להשתמש במתודת write שהמידע שהיא מקבלת הוא אובייקט מסוג ClipboardItem שהוא אובייקט מובנה בג'אווהסקריפט שאנחנו יכולים להצהיר על הסוג שלו. למשל:

function setClipboard(text) {
  let data = [new ClipboardItem({ "text/plain": text })];

  navigator.clipboard.write(data).then(function() {
    /* success */
  }, function() {
    /* failure */
  });
}

ואם אנו רוצים לבצע העתקה של תמונה או canvas, אני אצטרך לבצע המרה ל-blob ואז הדבקה. למשל:

function copyCanvasContentsToClipboard(canvas, onDone, onError) {
  canvas.toBlob(function (blob) {
    let data = [new ClipboardItem({ [blob.type]: blob })];

    navigator.clipboard.write(data).then(function () {
      onDone();
    }, function (err) {
      onError(err);
    })
  });
}

את הדוגמאות המאוד פשוטות האלו לקחתי מ-MDN. רוב הזמן השתמשתי בקוד הפשוט של העתקת הטקסט כי זה בד"כ מה שמשתמשים בו – כדי לסייע למשתמשים להעתיק קודים מסובכים למשל (כמו UUID או קישורים).מדובר ב-promise אז או שאנו עוטפים אותה ב-async-await או שאנו משתמשים ב-then. במקרה הזה כתבתי ג׳אווהסקריפט מודרני ופשוט של async-await.

קריאה

זו בעצם קריאה מה-clipboard. ממש לראות מה יש שם. אם מדובר בטקסט, אז יש לנו את מתודת readText שגם היא מחזירה פרומיס.

navigator.clipboard.readText();

וכמובן שיש לנו במקרה שמדובר בתמונה או סוג מידע אחר, את מתודת read שעליה לא ארחיב.

ברוב המקרים אתם תרצו להשתמש ב-readText וב-writeText. מסיבות אבטחה, המשתמש יקבל אינדיקציה לכך שאתם הולכים להשתמש ביכולת הקריאה – כלומר לראות מה יש לו ב-clipboard. למה? כדי שלא תוכלו לפשפש בסודותיו. זה מידע שיכול לבוא מחוץ לאתר ולסקריפט שלכם. האזהרה תבוא ככה:

בקשת אישור של האתר ברגע שיש כתיבה

לכתוב אל ה-clipboard לא מחייב הרשאה. רק קריאה תקפיץ את החלון הזה למשתמשים.

אם יש לכם feature-toggle או Permissions-Policy, אתם יכולים לאסור על סקריפטים אפילו לבקש את ההרשאה הזו (זו הסיבה שהקוד לעיל לא יעבוד ב-codepn.io, כי הם כיבו את היכולת של סקריפטים לגשת ל-clipboard).

אירועי Clipboard

מה שלא מחייב הרשאות משתמש הוא עבודה עם האירועים הקשורים ל-clipboard. כאשר משתמש מבצע העתקה (קונטרול C או קונטרול X או כפתור ימני והעתקה או גזירה), אנו יכולים להתפס על האירוע הזה. מדובר באירוע כמו כל אירוע. הוא אירוע שאנו יכולים להאזין לו גלובלית או להצמיד אותו לאלמנט מסוים שנמצא בפוקוס. בד״כ שמים אותו גלובלית.

ההסבר יותר מסובך מהקוד. הקוד נראה בפועל ככה:

document.addEventListener('copy', (event) => {
    const selection = document.getSelection();
    event.clipboardData.setData('text/plain', selection.toString().toUpperCase());
    event.preventDefault();
});

document.addEventListener('cut', (event) => {
    const selection = document.getSelection();
    event.clipboardData.setData('text/plain', selection.toString().toUpperCase());
    event.preventDefault();
});

והקוד הזה מתלבש על אירועי העתקה, לוקח את מה שהעתקנו באמצעות document.getSelection ואז משנה את המידע שנכנס לתוך ה-clipboard, משנה את האותיות לאותיות גדולות וזהו.

הנה הדמו שיעבוד יפה מאוד ב-codepen כי האירועים עובדים בלי קשר ל feature-toggle:

See the Pen clipboard events by Ran Bar-Zik (@barzik-the-vuer) on CodePen.

פינת אבטחת המידע

אם אתם ממש רוצים לעצבן את המשתמשים שלכם, אתם יכולים להשתמש באירוע הזה כדי לשנות את הטקסט (למשל להוסיף את המשפט: ״הועתק מהאתר של רן בר-זיק החתיך וההורס!״) אבל אם אתם יותר זדוניים – בהחלט אפשר להשתמש בזה להתקפות מעניינות.

למשל, לקחת את הטקסט ולהוסיף לו תוספת קטנה:

<img src="a" onerror="alert(1)" />

זו בעצם התקפת XSS שאפשר למשל ליצור על אנשים שמשתמשים ב WYSIWYG כמו ג׳ימייל. לגרום להם להעתיק טקסטים ולהדביק אותם וברגע שהם מדביקים, הפיילואוד שיש ב-onerror יעבוד. במקרה הזה alert ובמקרה אחר לא. והמשתמש לא ידע כלום. נכון, גם דפדפנים וגם עורכי WYSIWYG מכירים את הפרצה הזו, אבל חוקר אבטחה בשם Michał Bentkowski כתב מחקר מעמיק שמראה איך הוא מצליח לעקוף את ההגנות האלו. מאוד מעניין לדעתי. האם צריך להכנס ללחץ? ובכן – אין התקפות כאלו באוויר הפתוח אבל ללא ספק מדובר פה בהתקפה מעניינת.

מה שעוד אפשר לעשות כדי לבצע ניטור זה להוסיף zero width characters לטקסט המועתק וכך – אם מדובר בטקסט מסווג, לעלות על מי שיוציא אותו החוצה. כתבתי על הטכניקה הזו לא מעט פעמים (אני גם משתמש בה כאמצעי הגנה על ספר הג׳אווהסקריפט שלי). ועוד מיני תעלולים שונים. כמו למשל לשלוח טלמטריה (בקשת AJAX ללוגר) בכל פעם שהמשתמש החצוף מבצע העתקה מהאתר שלכם. ומסתבר שטיק-טוק עושים את זה באפליקציה שלהם (יחד עם עוד נבלות) אבל אני כבר חורג.

הכרת ה-API של ה-clipboard היא שימושית במקרה ויש לכם קוד או טקסט שהמשתמשים שלכם צריכים להעתיק ואתם רוצים להקל עליהם. היא פותחת פתח לצרות מאוד מעניינות שכרגע תיאורטיות אבל לכו תדעו.

וכמובן פותחת לכם את הדרך להוסיף ״כל הזכויות שמורות לרן בר-זיק החתיך״ אם אתם ממש דבילים.

כדאי תמיד להשאר מעודכנים! אם יש לכם טלגרם, בדקו את ערוץ הטלגרם של האתר שבו אני מעדכן על פוסטים חדשים 🙂 אם אתם רוצים ללמוד תכנות באופן מקיף ומסודר, הצטרפו לאלפי הלומדים בפרויקט "ללמוד ג'אווהסקריפט בעברית" שמלמד לתכנת בג'אווהסקריפט, ב-Node.js ובריאקט וגם מלמד על תרומה לקוד פתוח. גם ספרים דיגיטליים וגם ספרים מודפסים. בשיתוף הקריה האקדמית אונו ובתמיכת חברות מובילות כגון Wix, Outbrain, Elementor, Iron Source, Chegg, Really Good ועוד.
JavaScript

3 תגובות

  1. מישהו הגב יולי 1, 2020 בשעה 1:02 am

    זה למה אפל זורקת WebAPI
    https://www.zdnet.com/article/apple-declined-to-implement-16-web-apis-in-safari-due-to-privacy-concerns/

  2. יואל הגב יולי 1, 2020 בשעה 4:47 pm

    הציק לי בעין
    "קודים מסובכים"
    נראה לי שיותר תקיו לומר
    "קטעי קוד מסובכים

    אחלה מאמר מעניין ומרתק
    תודה

  3. משתמש אנונימי (לא מזוהה) הגב יולי 23, 2020 בשעה 9:45 am

    מאמר מעולה!!!
    תודה!!!

השארת תגובה

ביטול

ללמוד ג'אווהסקריפט בעברית

ללמוד לתכנת ג'אווהסקריפט בעברית שגייס יותר משלוש מאות אלף שקל ולמעלה מ-2000 תומכים - בואו ללמוד עכשיו איך לתכנת.

רשימת הנושאים
  • מדריכים
    • ריאקט
    • טייפסקריפט
    • ECMAScript 6
    • ES20XX
    • Node.js
    • Express
    • רספברי פיי
    • Babel
    • docker
    • MongoDB
    • Git
    • לימוד MySQL
    • SASS
    • jQuery
    • CSS3
    • HTML 5
    • SVN
    • LESS
  • פיתוח אינטרנט
    • פתרונות ומאמרים על פיתוח אינטרנט
    • jQuery Scripts
    • jQuery למתקדמים
    • יסודות בתכנות
    • נגישות אינטרנט
  • חדשות אינטרנט
  • מידע כללי על אינטרנט
    • רשת האינטרנט
    • בניית אתרי אינטרנט
  • rss logo

    לכל המאמרים

    לכל המאמרים שפורסמו באינטרנט ישראל משנת 2008 ועד עכשיו.
  • rss logo

    RSS Feed

    משתמשים בקורא RSS? אם כן, עקבו אחרי אינטרנט ישראל באמצעות פיד ה-RSS!
    מה זה RSS?
  • Twitter logo

    עקבו אחרי בטוויטר

    בחשבון הטוויטר שלי אני מפרסם עדכונים מהירים על חדשות בתחום התכנות והיזמות, התרעות על מצבי חירום ורכילות בוערת על תחום הווב.
    מה זה טוויטר?
  • facebook like image

    ערוץ הטלגרם של אינטרנט ישראל

    בערוץ הטלגרם של אינטרנט ישראל אני מפרסם את הפוסטים של באתר וכן עדכונים טכנולוגיים נוספים.
    מה זה טלגרם?
  • github logo

    הפרויקטים שלי בגיטהאב

    הפרויקטים שאני כותב ושוחררו לציבור ברישיון קוד פתוח נמצאים ברובם בגיטהאב.
חיפוש

כל הזכויות שמורות לרן בר-זיק ולאינטרנט ישראל | מדיניות הפרטיות של אתר אינטרנט ישראל | אתר אינטרנט ישראל נגיש לפי תקן WCAG 2.0 AA | הצהרת הנגישות של האתר | אבטחת מידע ודיווח על בעיית אבטחת מידע

גלילה לראש העמוד