Category: UI5 Integrations

  • Email and Password Login Integration in SAP UI5 using Google Firebase

    Introduction

    Welcome to the comprehensive guide on integrating email and password login functionality in SAP UI5 using Google Firebase! Securing your SAP UI5 application with user authentication is crucial for protecting sensitive data and providing a personalized user experience. By leveraging the power of Google Firebase, you can easily implement a robust and secure login system.

    In this tutorial, we will walk you through the step-by-step process of integrating email and password login functionality into your SAP UI5 application. By following these instructions, you’ll be able to authenticate users using their email and password, ensuring a seamless and secure login experience.

    We’ll start by setting up Google Firebase and enabling the Email/Password authentication provider. Firebase simplifies the authentication process, handling all the necessary backend operations for you. You’ll learn how to install the Firebase SDK into your SAP UI5 project and initialize Firebase with your project’s configuration.

    Next, we’ll guide you in implementing the login functionality within your SAP UI5 app. You’ll create a login page or dialog where users can enter their email and password. We’ll demonstrate how to capture user input and utilize Firebase’s signInWithEmailAndPassword method to authenticate the user securely.

    Furthermore, we’ll show you how to handle authentication state events to dynamically adjust your application’s behavior based on whether a user is logged in or logged out. This will enable you to tailor the user experience and provide access to protected routes or resources.

    Lastly, we’ll emphasize the importance of testing and refining your email and password login integration. Ensuring that users can successfully log in, handling authentication errors gracefully, and implementing additional security measures such as password reset functionality or email verification will enhance the overall user experience.

    By the end of this tutorial, you’ll have a fully functional email and password login system integrated seamlessly into your SAP UI5 application, powered by the robust authentication capabilities of Google Firebase.

    So let’s get started on this exciting journey of empowering your SAP UI5 app with secure user authentication using email and password login integration with Google Firebase!

    How to do Email and Password Login Integration in SAP UI5 using Google Firebase

    Integrating email and password login functionality in SAP UI5 using Google Firebase is a powerful way to provide secure authentication for your application users. Follow these steps to accomplish this integration:

    1. Set up Google Firebase: Create a Firebase project and enable the Authentication service. Navigate to the Firebase console and click on “Authentication” in the left-hand menu. Enable the “Email/Password” authentication provider.
    2. Install Firebase SDK: In your SAP UI5 project, open the terminal or command prompt and navigate to the project directory. Run the following command to install the Firebase JavaScript SDK:
      npm install firebase
      

       

    3. Initialize Firebase: Create a new JavaScript file in your SAP UI5 project, such as “firebase.js”. Import the Firebase SDK and initialize Firebase with your project’s configuration. Obtain the Firebase configuration object from the Firebase console by navigating to Project Settings > General > Your apps > Firebase SDK snippet. Copy the code snippet for the web app configuration and paste it into your “firebase.js” file.
    4. Implement the login functionality: In your SAP UI5 app, create a login page or a dialog where users can enter their email and password. Capture the user’s input and use the Firebase SDK methods to authenticate the user. For example, use the signInWithEmailAndPassword method to authenticate the user with their email and password.
      Enable Authentication in Google Firebase
    5. Handle authentication events: Firebase provides authentication state events that allow you to handle changes in the user’s authentication status. Implement event listeners to detect when a user logs in or logs out. You can display different content or redirect the user to different pages based on their authentication status.
    6. Secure routes and resources: To ensure that only authenticated users can access certain routes or resources in your SAP UI5 app, implement security checks using Firebase Authentication. You can restrict access to specific routes or components based on the user’s authentication status or their assigned roles.
    7. Test and refine: Test the email and password login integration thoroughly to ensure it functions as expected. Verify that users can log in with their credentials and that appropriate error handling is in place. Consider adding features like password reset functionality or email verification to enhance the user experience and security.

    By following these steps, you can successfully integrate email and password login functionality using Google Firebase in your SAP UI5 application. Remember to consult the Firebase documentation and the SAP UI5 guidelines for more detailed instructions and best practices. Happy coding!

    UI5 Code to Integrate Email and Password Login using Google Firebase

    Login.view.xml

    <mvc:View controllerName="firebaseApp.firebaseApp.controller.Login" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m"
        xmlns:html="http://www.w3.org/1999/xhtml" xmlns:core="sap.ui.core">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Email and Password Login Integration in SAP UI5 using Google Firebase">
                        <content>
                            <VBox height="100%" alignItems="Center">
                                <HBox height="100%" alignItems="Center">
                                    <Image height="100px" class="sapUiLargeMarginEnd"
                                        src="https://www.loc-online.co.uk/berkshire-loc/wp-content/uploads/sites/23/2020/06/Screenshot-2020-05-28-at-16.35.37-266x300.png"/>
                                    <IconTabBar id="idIconTabBarNoIcons" expanded="{device>/isNoPhone}" selectedKey="mail" class="sapUiResponsiveContentPadding">
                                        <items>
                                            <IconTabFilter text="Email Login" key="mail">
                                                <VBox id="idMailDetails">
                                                    <Label design="Bold" text="Enter Registered Email ID" required="true"/>
                                                    <Input width="300px" id="idu_admin" required="true" placeholder="username@mail.com" submit="onEmailSignin"/>
                                                    <Label design="Bold" text="Enter Password" required="true"/>
                                                    <Input width="300px" id="idp_admin" required="true" type="Password" placeholder="*****" submit="onEmailSignin"/>
                                                    <HBox>
                                                        <Button width="145px" class="sapUiTinyMarginEnd" text="Sign In" press="onEmailSignin"/>
                                                        <Button width="145px" text="Reset" press="onReset"/>
                                                    </HBox>
                                                </VBox>
                                            </IconTabFilter>
                                        </items>
                                    </IconTabBar>
                                </HBox>
                            </VBox>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

     

    Login.controller.js

    sap.ui.define([
        "sap/ui/core/mvc/Controller"
    ], function (Controller) {
        "use strict";
    
        return Controller.extend("firebaseApp.firebaseApp.controller.Login", {
            onInit: function () {
                
            },
    
            onEmailSignin: function (oEvent) {
                var that = this;
                sap.ui.core.BusyIndicator.show();
                var email = this.byId("idu_admin").getValue();
                var password = this.byId("idp_admin").getValue();
                var errorMessage = "";
                // Create a Fireauth Auth reference
                var oModel = this.getView().getModel("fbModel").getData();
                var fireAuth = oModel.fireAuth;
                var firestoreData = oModel.firestore;
                fireAuth.signInWithEmailAndPassword(email, password).then(function (usersigned) {
                    sap.ui.core.BusyIndicator.hide();
                    MessageBox.success("You are Logged in!");
                    that.onReset();
                }).catch(function (error) {
                    sap.ui.core.BusyIndicator.hide();
                    // Handle Errors here.
                    errorMessage = error.message;
                    MessageBox.error(errorMessage);
                });
            },
    
            onReset: function (oEvent) {
                this.byId("idu_admin").setValue("");
                this.byId("idp_admin").setValue("");
            }
        });
    });

    Output

    Email and Password Login Integration in SAP UI5 using Google Firebase

  • SAP Fiori Launchpad Extensibility

    Introduction

    Unlock the full potential of your SAP Fiori Launchpad with seamless extensibility. Discover the power of customizing and enhancing your Fiori Launchpad to cater to your unique business needs. SAP Fiori Launchpad Extensibility allows you to tailor the user interface, personalize tiles, and integrate additional applications effortlessly. Maximize productivity and user satisfaction by optimizing your Fiori Launchpad to align with your organization’s processes and workflows. Unleash innovation and empower your users with a tailored and intuitive Fiori Launchpad experience through SAP Fiori Launchpad Extensibility.

    Steps for ‘SAP Fiori Launchpad Extensibility’ using WebIDE

    Here are the steps to perform SAP Fiori Launchpad Extensibility using WebIDE:

    1. Launch SAP WebIDE: Open SAP Web Integrated Development Environment (WebIDE) in your browser. Log in with your credentials and navigate to the development environment.

    2. Create or Open a Project: Create a new project or open an existing project in WebIDE that is associated with the SAP Fiori Launchpad you want to extend.

    3. Locate the “Extensibility” Folder: In your project structure, locate the “Extensibility” folder. This folder contains the necessary files and configurations for Fiori Launchpad extensibility.

    4. Configure the “Extensibility” Files: Within the “Extensibility” folder, you will find files such as “manifest.json” and “Component.js”. These files define the settings and behavior of your Fiori Launchpad extension. Customize these files to meet your requirements.

    5. Define the Extensions: Identify the areas or components of the Fiori Launchpad that you want to extend or modify. This can include adding custom tiles, enhancing existing tiles, or integrating new applications. Use the appropriate extension points defined in the “manifest.json” file to define the desired extensions.

    6. Develop the Extensions: Implement the required logic and UI changes for your Fiori Launchpad extensions. This involves developing new UI views, controllers, and models as per your customization needs. Leverage the Fiori development guidelines and best practices during this process.

    7. Test and Validate: Once the extensions are implemented, test them thoroughly to ensure they work as expected. Validate the behavior and appearance of your custom tiles, application integrations, and any other modifications made to the Fiori Launchpad.

    8. Deploy and Activate: Once you are satisfied with the extensions and they have been successfully tested, deploy the changes to your SAP Fiori Launchpad environment. Activate the extensions to make them visible and accessible to the users.

    9. Monitor and Maintain: Continuously monitor and maintain your Fiori Launchpad extensions to ensure their optimal performance and compatibility with future updates or changes in your SAP landscape. Regularly review and update the extensions based on evolving business requirements.

    By following these steps, you can effectively perform SAP Fiori Launchpad extensibility using SAP WebIDE, enabling you to tailor and enhance the Fiori Launchpad to meet your organization’s specific needs.

    Steps for ‘SAP Fiori Launchpad Extensibility’ using SAP BAS

    Here are the steps to perform SAP Fiori Launchpad Extensibility using SAP Business Application Studio (BAS):

    1. Launch SAP BAS: Open SAP Business Application Studio in your browser. Log in with your credentials and navigate to the development environment.

    2. Create or Open a Project: Create a new project or open an existing project in SAP BAS that is associated with the SAP Fiori Launchpad you want to extend.

    3. Configure the Launchpad Descriptor (lpd_cust): Locate the “lpd_cust” folder in your project structure. This folder contains the configuration files for Fiori Launchpad extensibility. Open the “lpd_cust” file and customize it to define your Launchpad’s behavior and extensions.

    4. Define the Extensions: Identify the areas or components of the Fiori Launchpad that you want to extend or modify. Use the “lpd_cust” file to define the desired extensions, such as adding custom tiles, modifying existing tiles, or integrating new applications. Follow the provided guidelines and syntax to specify the extensions accurately.

    5. Develop the Extensions: Implement the required logic and UI changes for your Fiori Launchpad extensions. This involves developing new UI views, controllers, and models as per your customization needs. Leverage the Fiori development guidelines and best practices during this process.

    6. Test and Validate: Thoroughly test your Fiori Launchpad extensions to ensure they function correctly. Validate the behavior and appearance of your custom tiles, application integrations, or any other modifications made to the Launchpad. Use the available testing tools and techniques to validate the extensions.

    7. Deploy and Activate: Once you are satisfied with the extensions and they have been successfully tested, deploy the changes to your SAP Fiori Launchpad environment. Activate the extensions to make them visible and accessible to the users.

    8. Monitor and Maintain: Continuously monitor and maintain your Fiori Launchpad extensions to ensure their optimal performance and compatibility with future updates or changes in your SAP landscape. Regularly review and update the extensions based on evolving business requirements.

    By following these steps, you can leverage SAP Business Application Studio (BAS) to perform SAP Fiori Launchpad extensibility effectively. Customize and enhance your Fiori Launchpad to align with your organization’s requirements and provide an intuitive user experience for your users.

    How to Create a Basic Extension Plugin for Fiori Launchpad

    Step 01: Enable ‘SAP Fiori Launchpad Extensibility’ on WebIDE as shown below:

    SAP Fiori Launchpad Extensibility

    Step 02: Click on Create New Project –> Project from Template

    Step 03: Choose the ‘SAP Fiori Launchpad Plugin’ template and click Next.

    Step 04: Enter the Project Name, click Next

    Step 05: Provide Plugin ID, and Plugin Title, and click Finish

    Step 06: Edit the Component.js file

    Step 07: Run the plugin by clicking “Run as SAP Fiori Launchpad Sandbox”

  • Graph API Integration with SAP UI5

    Introduction

    Welcome to our comprehensive guide on Graph API integration with SAP UI5! In this article, we will explore the seamless integration of Graph API, a powerful data query and manipulation tool from Microsoft, with SAP UI5 applications. Discover how combining the capabilities of Graph API and SAP UI5 can enhance data connectivity, streamline business processes, and deliver a superior user experience. We will delve into the key features, implementation strategies, and best practices for integrating Graph API with SAP UI5. Unleash the potential of data-driven applications by harnessing the power of Graph API and SAP UI5 integration. Let’s embark on a journey that empowers your application with efficient data access, advanced analytics, and real-time collaboration. Join us as we explore the boundless possibilities of Graph API integration with SAP UI5!

    What is Microsoft Graph API

    Microsoft Graph API is a comprehensive RESTful API provided by Microsoft that allows developers to access a wide range of Microsoft 365 services and data, including Office 365, Azure Active Directory, SharePoint, OneDrive, Outlook, and more. It serves as a unified gateway to access and interact with various Microsoft services and their underlying data.

    With Microsoft Graph API, developers can build applications that leverage the rich functionality and data available across Microsoft 365 services. It provides a consistent and efficient way to retrieve, create, update, and delete data in a standardized manner, simplifying the development process and reducing the need for multiple API calls.

    Through Graph API, developers can access resources such as users, groups, files, calendars, contacts, messages, and other entities within Microsoft 365. They can perform tasks like retrieving user profiles, accessing documents, sending emails, creating events, managing permissions, and more.

    Graph API supports a variety of authentication mechanisms, including Azure Active Directory (Azure AD), OAuth 2.0, and Microsoft account authentication. This ensures secure access to Microsoft 365 resources and protects user data.

    By integrating Microsoft Graph API with SAP UI5, developers can unlock powerful capabilities, such as retrieving and manipulating data from Microsoft 365 services, enabling collaboration features, accessing user information, and integrating with various business workflows. It provides seamless connectivity between SAP applications and Microsoft services, facilitating enhanced productivity and enriched user experiences. Read more here.

    Steps to Create Authorization Key of Graph API

    To create an authorization key (also known as an access token) for Microsoft Graph API, you need to follow these steps:

    1. Register your application: Start by registering your application in the Azure portal. This registration enables your application to authenticate and authorize access to Microsoft Graph API. Navigate to the Azure portal (https://portal.azure.com/) and sign in with your Azure account.

    Microsoft Azure Portal

    2. Create an Azure AD application: In the Azure portal, go to the “Azure Active Directory” section and select “App registrations” (or “App registrations (Legacy)” for older versions). Click on the “New registration” (or “New application registration”) button to create a new application.

    Create Azure AD User

    3. Provide application details: Fill in the required details for your application, such as a name, supported account types, and redirect URI (if applicable). The redirect URI is the URL where users are redirected after authentication.

    New Application

    Certificate & Secrets

    4. Configure API permissions: In the application settings, navigate to the “API permissions” (or “Required permissions”) section. Click on the “Add a permission” button and select the Microsoft Graph API.

    5. Select required permissions: Choose the required permissions based on the operations your application needs to perform. For example, if you need to read user profiles, select the appropriate User.Read scope. Click on the “Grant admin consent” button to grant these permissions for your application (if you have the necessary permissions).

    6. Obtain the authorization code: To obtain an authorization code, construct the authorization URL by specifying the appropriate scopes and redirect URI. Users will be prompted to sign in and grant consent to your application. After successful authentication and consent, the authorization code will be included in the redirected URL.

    7. Exchange authorization code for an access token: Using the authorization code, make a POST request to the token endpoint of Microsoft Graph API. Include the necessary parameters like client ID, client secret (if applicable), redirect URI, and authorization code. The response will contain an access token, which is the authorization key you can use to make authenticated requests to Microsoft Graph API.

    Note: The specific implementation details may vary based on your programming language and platform. You can refer to the official Microsoft Graph API documentation for more detailed instructions and code examples specific to your scenario.

    Remember to handle the authorization key securely and refresh it as needed, following the recommended practices to ensure the security of your application and user data.

    Steps to integrate Graph API using JavaScript

    You can download Microsoft Graph API Postman Collection here.

    Microsoft API Postman Collection

    To integrate Microsoft Graph API using JavaScript, you can follow these steps:

    1. Set up authentication:
    – Register your application in the Azure portal and obtain the necessary client ID and client secret (or client credentials) for authentication.
    – Install the required JavaScript libraries, such as the Microsoft Authentication Library (MSAL) or adal.js, which provide the necessary functions for authentication.

    2. Obtain an access token:
    – Use the authentication library to initiate the authentication process and obtain an access token for Microsoft Graph API.
    – Configure the required scopes and authentication parameters, such as client ID, redirect URI, and permissions, in your authentication code.

    3. Make API requests:
    – Once you have obtained an access token, you can use it to make API requests to Microsoft Graph API.
    – Use AJAX or fetch API to send HTTP requests to the appropriate API endpoints. Include the access token in the Authorization header of the request.
    – Refer to the Microsoft Graph API documentation for the specific endpoints and data you want to interact with.

    4. Handle API responses:
    – Parse and process the responses received from Microsoft Graph API.
    – Use JavaScript functions to extract the required data from the response objects and display or manipulate it as needed in your application.

    5. Implement error handling:
    – Handle potential errors that may occur during the API integration process, such as authentication failures, invalid requests, or API rate limits.
    – Implement appropriate error handling and display error messages to the user when necessary.

    6. Test and debug:
    – Test your integration by running your application and verifying that the API requests and responses function as expected.
    – Use browser developer tools or debugging tools to identify and resolve any issues or errors that may arise during the integration.

    Remember to follow best practices for securely handling access tokens, implementing proper authentication flows, and handling user consent and permissions when working with Microsoft Graph API.

    Please note that the specific implementation details may vary depending on the JavaScript libraries or frameworks you are using and the specific requirements of your application. Consult the documentation and resources provided by Microsoft for more detailed instructions and code examples for integrating Microsoft Graph API using JavaScript.

    Steps to integrate Graph API in SAP UI5

    To integrate Microsoft Graph API in SAP UI5, you can follow these steps:

    1. Obtain the necessary authorization and authentication:
    – Register your application in the Azure portal and obtain the required client ID and client secret (or client credentials) for authentication.
    – Set up the necessary authentication mechanisms, such as OAuth 2.0 or Azure Active Directory, to authenticate your application and obtain an access token for Microsoft Graph API.

    2. Create a service or utility class:
    – In your SAP UI5 application, create a service or utility class responsible for making HTTP requests to Microsoft Graph API.
    – Use SAP UI5’s built-in AJAX or OData libraries, such as `jQuery.ajax` or `sap.ui.model.odata.v2.ODataModel`, to handle HTTP requests and responses.

    3. Configure the API endpoint:
    – Define the API endpoint URLs for the specific Microsoft Graph API operations you want to perform, such as retrieving user profiles, accessing messages, or managing calendars.
    – Include the necessary headers, such as the Authorization header with the access token, in your API requests.

    4. Make API calls:
    – Use the defined API endpoint URLs and the configured headers to make HTTP requests to Microsoft Graph API within your service or utility class.
    – Leverage the appropriate AJAX or OData functions provided by SAP UI5 to send the requests and handle the responses.
    – Parse and process the responses received from Microsoft Graph API and extract the required data for use within your SAP UI5 application.

    5. Implement error handling:
    – Handle potential errors and exceptions that may occur during the API integration process, such as authentication failures, invalid requests, or API rate limits.
    – Implement appropriate error handling mechanisms, such as displaying error messages or triggering fallback actions, to handle any errors or exceptions gracefully.

    6. Integrate the service in your SAP UI5 application:
    – Use the created service or utility class within your SAP UI5 application to access and utilize the Microsoft Graph API functionality.
    – Integrate the API calls and the retrieved data with the relevant UI components, models, or controllers in your SAP UI5 application to provide a seamless user experience.

    View.xml

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:ndc="sap.ndc" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m"
        xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Graph API Integration in SAP UI5">
                        <content>
                            <Button id="button" text="Show User Details" press="onFetchUser"/>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

     

    Controller.js

    sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "sap/m/MessageBox",
        "sap/m/MessageToast",
        "sap/ui/model/json/JSONModel",
    
    ], function (Controller, MessageBox, MessageToast, JSONModel) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onInit: function () {},
    
            onFetchUser: function (oEvent) {
                var settings = {
                    "url": "https://cors-anywhere.herokuapp.com/https://login.microsoftonline.com/9ff78c75-dbce-4557-83b0-36953dc9a017/oauth2/v2.0/token",
                    "method": "POST",
                    "timeout": 0,
                    "headers": {
                        "Content-Type": "application/x-www-form-urlencoded",
                        "SdkVersion": "postman-graph/v1.0",
                        "Cookie": "fpc=AmXUYBpiSB1Onw0A3xawYrYYPDVEAQAAADZ1-dsOAAAAQ7i_kAIAAABnc_nbDgAAAJzET7QBAAAA1nP52w4AAAA; stsservicecookie=estsfd; x-ms-gateway-slice=estsfd"
                    },
                    "data": {
                        "grant_type": "client_credentials",
                        "client_id": "ba945c3f-8687-4a6a-a95b-1aaad7323872",
                        "client_secret": "SW58Q~YxPf86UZhGYfhzTE7ZXKHOm.eKZ4bH4cd0",
                        "scope": "https://graph.microsoft.com/.default"
                    }
                };
    
                $.ajax(settings).done(function (response) {
                    console.log(response.access_token);
    
                    var settings = {
                        "url": "https://graph.microsoft.com/v1.0/users/d3f7739f-55f4-41e1-bc3a-2a36e31922f0",
                        "method": "GET",
                        "timeout": 0,
                        "headers": {
                            "Content-Type": "application/json",
                            "SdkVersion": "postman-graph/v1.0",
                            "Authorization": "Bearer " + response.access_token
                        },
                    };
    
                    $.ajax(settings).done(function (response) {
                        console.log(response);
                    });
                });
            }
        });
    });

     

    Output Screen

    Graph API UI5

    Output Generated via Graph API

    Graph API output

    7. Test and debug:
    – Test the integration by running your SAP UI5 application and verifying that the API requests and responses function as expected.
    – Use SAP UI5’s debugging tools or browser developer tools to debug any issues or errors that may arise during the integration.

    Ensure that you handle access token management securely, implement proper error handling, and follow best practices for integrating external APIs within SAP UI5 applications.

    Please note that the specific implementation details may vary based on the SAP UI5 version, architecture, and the specific requirements of your application. Consult the SAP UI5 documentation and resources for more detailed instructions and code examples for integrating Microsoft Graph API in SAP UI5.

    Testing Graph API

    Test your APIs using Graph API Explorer here. You can test all the available APIs here, using your login. Like I have tried to run the first basic API to fetch my own user details:

    Graph API Explorer

  • Google Maps Integration in SAP UI5

    Introduction

    Welcome to our comprehensive guide on Google Maps integration in SAP UI5! In this article, we will explore the seamless integration of these two powerful technologies to enhance the user experience and unlock a world of geospatial possibilities. Discover how the integration of Google Maps and SAP UI5 can revolutionize your application by providing intuitive and interactive mapping functionalities. We will delve into the key features, implementation strategies, and best practices to ensure a successful integration. Get ready to embark on a journey that combines the strength of SAP UI5 with the versatility of Google Maps, resulting in an unparalleled user experience and improved business outcomes. Let’s dive in and explore the limitless potential of Google Maps integration in SAP UI5!

    When we need Google Maps Integration in SAP UI5

    Google Maps integration in SAP UI5 becomes essential in various scenarios where geospatial information and mapping capabilities are required within SAP applications. Here are a few instances when integrating Google Maps with SAP UI5 can be beneficial:

    1. Location-Based Services: When you need to incorporate location-based services into your SAP UI5 application, such as displaying customer locations, tracking shipments, or finding the nearest store or service center.

    2. Geographical Data Visualization: If you have large volumes of geographical data that need to be visualized effectively, Google Maps integration can help you present the information in a user-friendly and interactive manner.

    3. Route Planning and Optimization: When your SAP application involves route planning, delivery management, or field service operations, integrating Google Maps allows you to calculate optimized routes, estimate travel distances and durations, and provide real-time traffic information.

    4. Geolocation Tracking: If you require real-time tracking of assets, vehicles, or personnel within your SAP application, Google Maps integration enables you to track and display their positions on a map, facilitating monitoring and decision-making processes.

    5. Address Validation and Geocoding: When it’s necessary to validate and standardize addresses entered by users or perform geocoding (converting addresses into geographic coordinates), integrating Google Maps can ensure accurate and reliable data.

    6. Location Intelligence and Analytics: If you want to leverage location-based insights to enhance business intelligence and analytics, integrating Google Maps with SAP UI5 enables you to overlay geographical data with other business data, facilitating data-driven decision-making.

    By integrating Google Maps with SAP UI5, you can unlock a wide range of geospatial functionalities, enrich your application with interactive maps, and provide a more intuitive and engaging user experience.

    How to generate a Google Map API Key

    To generate a Google Maps API key, follow these steps:

    1. Go to the Google Cloud Platform Console: Visit the Google Cloud Platform Console at https://console.cloud.google.com/.

    2. Create a new project: If you don’t have a project already, create a new one by clicking on the “Select a project” drop-down menu at the top of the page and selecting “New Project.” Give your project a name and click “Create.”

    3. Enable the Maps JavaScript API: In the Cloud Platform Console, click on the “Enable APIs and Services” button. Search for “Maps JavaScript API” and select it from the results. Click on the “Enable” button to enable the API for your project.

    4. Set up API credentials: From the left sidebar, click on “Credentials” and then click on the “Create Credentials” button. Select “API key” from the dropdown menu.

    5. Restrict your API key (optional): For security purposes, it’s recommended to restrict your API key to only allow requests from specific websites or mobile apps. You can set up restrictions by clicking on the “Restrict key” button.

    6. Configure your API key: Give your API key a name for easy reference and configure any additional settings or restrictions as needed.

    7. Get your API key: Once you have configured your API key, it will be generated. Copy the API key and securely store it.

    Congratulations! You have successfully generated a Google Maps API key. Make sure to include this API key in your SAP UI5 application when making requests to the Google Maps API services.

    Types of Google Maps Integration in SAP UI5

    iFrame based Integration

    To perform iFrame-based integration in SAP UI5, you can follow these steps:

    1. Create an XML View: Define an XML view in your SAP UI5 application where you want to integrate the iFrame. This XML view will contain the iFrame control.
    2. Add iFrame control: Inside the XML view, add the iFrame control by using the <core:HTML> or <html:iframe> tag. Set the src attribute to specify the URL of the webpage or content you want to display within the iFrame.

      Example:

      <core:HTML content="<iframe src='https://www.example.com' width='100%' height='100%'></iframe>" />
      

       

    3. Adjust iFrame properties: Customize the iFrame by setting attributes such as width, height, scrolling, frameborder, etc., based on your requirements. These attributes define the appearance and behavior of the iFrame.
      <core:HTML content="<iframe src='https://www.example.com' width='800' height='600' scrolling='auto' frameborder='0'></iframe>" />
      

       

    4. Bind iFrame properties dynamically (optional): If you need to dynamically change the URL or other properties of the iFrame based on your application logic, you can bind the properties using data binding techniques provided by SAP UI5.
      <core:HTML content="<iframe src='{path>/iframeUrl}' width='100%' height='100%'></iframe>" />
      

       

    5. Style and position the iFrame: Apply CSS classes or inline styles to the iFrame or its parent containers to control the appearance, positioning, and responsiveness of the iFrame within your SAP UI5 application.
      <core:HTML content="<iframe src='https://www.example.com' width='100%' height='100%' class='myIframe'></iframe>" />
      

      In the CSS file:

      .myIframe {
          border: 1px solid #ccc;
          border-radius: 5px;
      }
      

       

    For Google Maps, first, get the source URL from here: https://www.maps.ie/create-google-map/

    And then add the following in the view file:

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:ndc="sap.ndc" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m"
        xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Google Map Integration in SAP UI5">
                        <content>
                            <!--Fixed Google Map without API Key and without serch functionality-->
                            <html:iframe width="100%" height="600"
                                src="https://maps.google.com/maps?width=100%25&amp;height=600&amp;hl=en&amp;q=Noida+(My%20Project%20Ideas)&amp;t=&amp;z=14&amp;ie=UTF8&amp;iwloc=B&amp;output=embed"></html:iframe>
                        
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

    Output

    Google Maps Integration using iFrame in UI5

    Google API-based Integration

    To perform Google API-based integration in SAP UI5, you can follow these steps:

    1. Obtain a Google Maps API Key: Generate a Google Maps API key by following the steps outlined in the previous response titled “How to generate a Google Map API Key.” This key will be required to access and use Google Maps API services.
    2. Load the Google Maps API library: In your SAP UI5 application, include the Google Maps JavaScript library by adding the following script tag to the HTML view or index.html file of your application.
      <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
      

      Replace YOUR_API_KEY with the API key you obtained in Step 1.

    3. Create a UI5 control for Google Maps integration: In your SAP UI5 application, create a control (such as a custom control or an extension of an existing control) that encapsulates the Google Maps functionality. This control will be responsible for rendering the map and interacting with the Google Maps API.
    4. Initialize the map: Within your UI5 control, initialize the Google Map by calling the appropriate JavaScript functions provided by the Google Maps API. This includes specifying the map container element, setting the initial center coordinates, zoom level, and any additional options you want to apply to the map.
      var map = new google.maps.Map(mapContainer, {
        center: { lat: 37.7749, lng: -122.4194 },
        zoom: 12,
      });
      

      Here, mapContainer represents the HTML element where the map will be rendered.

    5. Utilize Google Maps API services: You can now leverage various Google Maps API services within your UI5 control. These services include displaying markers, drawing shapes, geocoding, reverse geocoding, route calculation, and more. Refer to the Google Maps API documentation for details on each service and how to use them.
      // Example: Add a marker to the map
      var marker = new google.maps.Marker({
        position: { lat: 37.7749, lng: -122.4194 },
        map: map,
        title: 'San Francisco',
      });
      

      This example creates a marker at the specified coordinates and displays it on the map.

    6. ustomize and interact with the map: You can customize the map’s appearance, add event listeners for user interactions, and apply other styling and functionality as per your application requirements. Use the available Google Maps API functions and options to achieve this.
      // Example: Add a click event listener to the map
      map.addListener('click', function(event) {
        console.log('Clicked on the map at coordinates:', event.latLng);
      });
      

      This example logs the clicked coordinates to the console when the user clicks on the map.

      By following these steps, you can integrate Google Maps API functionality into your SAP UI5 application and leverage its powerful mapping capabilities to enhance the user experience and add geospatial functionality to your application.

    HTML code

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <!--<meta name="viewport" content="width=device-width, initial-scale=1.0">-->
            <title>My Project Ideas</title>
             <link rel="icon" type="image/x-icon" href="https://myprojectideas.com/wp-content/uploads/2021/08/cropped-Screenshot-2021-07-26-at-1.39.04-PM-32x32.png">
            <script id="sap-ui-bootstrap"
                src="resources/sap-ui-core.js"
                data-sap-ui-theme="sap_fiori_3"
                data-sap-ui-resourceroots='{"Test.Test": "./"}'
                data-sap-ui-compatVersion="edge"
                data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
                data-sap-ui-async="true"
                data-sap-ui-frameOptions="trusted">
            </script>
    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBXMbsWFS5fKJD7IX7-E__5ZWKFgZTNeqs&libraries=places" type ="text/javascript"> 
    </script>
    <style>
    .myMap {                   
    height: 100%;
    width: 100%  ;
    }
    </style>
        </head>
        <body class="sapUiBody">
            <div data-sap-ui-component data-name="Test.Test" data-id="container" data-settings='{"id" : "Test"}'></div>
        </body>
    </html>

     

    View Code

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:ndc="sap.ndc" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m"
        xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Google Map Integration in SAP UI5">
                        <content>
                            <VBox fitContainer="true" justifyContent="Center" alignItems="Center">
                                <HBox fitContainer="true" justifyContent="Center" alignItems="Center">
                                    <Input id="bntSearch" class="controls" type="text" placeholder="Search Box"/>
                                    <Button id="button" text="search" press="onAfterRendering"/>
                                    <Button id="Distance" text="Distance" press="onDistancePress"/>
                                </HBox>
                                <HBox fitContainer="true" justifyContent="Center" alignItems="Center">
                                    <Input id="FromDis" placeholder="From" visible="false"/>
                                    <Input id="ToDis" placeholder="To" visible="false"/>
                                    <Button id="Okay" text="Ok" visible="false" press="onOkayPress"/>
                                </HBox>
                                <HBox id="map_canvas" fitContainer="true" justifyContent="Center" alignItems="Center"></HBox>
                            </VBox>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

     

    Controller Code

    sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "sap/m/MessageBox",
        "sap/m/MessageToast",
        "sap/ui/model/json/JSONModel",
    
    ], function (Controller, MessageBox, MessageToast, JSONModel) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onInit: function () {
                this.getView().byId("map_canvas").addStyleClass("myMap");
            },
    
            onAfterRendering: function () {
                if (!this.initialized) {
                    this.initialized = true;
                    this.geocoder = new google.maps.Geocoder();
                    window.mapOptions = {
                        center: new google.maps.LatLng(28.5706333, 77.3272147),
                        zoom: 8,
                        mapTypeId: google.maps.MapTypeId.ROADMAP
                    };
                    //This is basically for setting the initial position of the map, ie. Setting the coordinates, for the place by default
    
                    var map = new google.maps.Map(this.getView().byId("map_canvas").getDomRef(), mapOptions);
                    var infowindow = new google.maps.InfoWindow;
                    var geocoder = new google.maps.Geocoder();
                    var marker = new google.maps.Marker({
                        map: map,
                    });
    
                    google.maps.event.addListener(map, "click", function (e) {
                        var lolatitude = e.latLng.lat(); //calculates latitude of the point of click
                        var lolongitude = e.latLng.lng() //calculates longitude of the point of click
                        jQuery.sap.require("sap.m.MessageToast");
                        sap.m.MessageToast.show("Lat" + lolatitude + "\n Lng" + lolongitude);
                        var latlng = new google.maps.LatLng("latlng", lolatitude, lolongitude);
                        var text1 = new sap.m.Text({
                            text: lolatitude
                        });
                        var text2 = new sap.m.Text({
                            text: lolongitude
                        });
                        window.point1 = lolatitude;
                        window.point2 = lolongitude;
                        geocodeLatLng(geocoder, map, infowindow, text1, text2);
    
                    });
                    //This function is for what should happen if a user left clicks on the map
                    function geocodeLatLng(geocoder, map, infowindow, text1, text2) {
                        var markers = [];
                        var input1 = text1.mProperties.text;
                        var input2 = text2.mProperties.text;
                        var latlng = {
                            lat: parseFloat(input1),
                            lng: parseFloat(input2)
                        };
    
                        geocoder.geocode({
                            'location': latlng
                        }, function (results, status) {
                            if (status === google.maps.GeocoderStatus.OK) {
                                if (results[1]) {
                                    //Here result will consist of many result, but we have to take fist result //itself, since that would be the appropriate one
                                    map.setZoom(11);
    
                                    function addMarker(location) {
                                        var marker = new google.maps.Marker({
                                            position: location,
                                            map: newmap1
                                        });
                                        markers.push(marker); // A marker is added to the point where it was clicked
                                    }
                                    var address1 = results[1].formatted_address;
    
                                    infowindow.setContent(results[1].formatted_address);
                                    infowindow.open(map, marker);
                                } else {
                                    window.alert('No results found');
                                }
                            } else {
                                window.alert('Geocoder failed due to: ' + status);
                            }
    
                        });
                    }
    
                    ////////////////////Distance//////////////////////
    
                } else if (this.initialized === true) {
                    this.actSearch()
                }
    
            },
    
            actSearch: function () {
                var newmap = new google.maps.Map(this.getView().byId("map_canvas").getDomRef(), mapOptions);
                var address = this.getView().byId("bntSearch").getValue();
                this.geocoder.geocode({
                    'address': address
                }, function (results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        newmap.setCenter(results[0].geometry.location);
                        newmap.setZoom(12);
                        var marker = new google.maps.Marker({
                            map: newmap,
                            position: results[0].geometry.location
                        });
                        //This function is for search. Here when a place is searched a marker is //applied and the map is zoomed to the particular position.
    
                    } else {
                        alert('Geocode was not successful for the following reason: ' + status);
                    }
                });
                return;
            },
            onDistancePress: function () {
                var loFrom = this.getView().byId("FromDis");
                var loTo = this.getView().byId("ToDis");
                var loOk = this.getView().byId("Okay");
                loOk.setVisible(true);
                loFrom.setVisible(true);
                loTo.setVisible(true);
            },
            //This function is triggered on click of distance button.
    
            onOkayPress: function () {
                //This function calculates approx. distance between the two places, since I //haven’t used Google Maps Distance API, therefore this ain’t the proper way //to calculate distance among the places
                var newmap1 = new google.maps.Map(this.getView().byId("map_canvas").getDomRef(), mapOptions);
                var address1 = this.getView().byId("FromDis").getValue();
                var address2 = this.getView().byId("ToDis").getValue();
                this.geocoder.geocode({
                    'address': address1
                }, function (results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        window.lolatitude1 = results[0].geometry.location.lat();
                        window.lolongitude1 = results[0].geometry.location.lng();
                        window.add1 = results[0].formatted_address.split(",", 1)[0]
                        newmap1.setCenter(results[0].geometry.location);
                        newmap1.setZoom(12);
                        var marker = new google.maps.Marker({
                            map: newmap1,
                            position: results[0].geometry.location
                        });
                    } else {
                        alert('Geocode was not successful for the following reason: ' + status);
                    }
                });
                this.geocoder.geocode({
                    'address': address2
                }, function (results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        window.lolatitude2 = results[0].geometry.location.lat();
                        window.lolongitude2 = results[0].geometry.location.lng();
                        window.add2 = results[0].formatted_address.split(",", 1)[0]
                        newmap1.setCenter(results[0].geometry.location);
                        newmap1.setZoom(10);
                        var marker = new google.maps.Marker({
                            map: newmap1,
                            position: results[0].geometry.location
                        });
                        sap.m.MessageToast.show("Approx. Distance Between" + " " + window.add1 + " " + "and" + " " + window.add2 + " " + "is" + " " +
                            getDistanceFromLatLonInKm(window.lolatitude1, window.lolongitude1, window.lolatitude2, window.lolongitude2) + "KM", {
                                width: "30em",
                                duration: 10000
                            });
    
                    } else {
                        alert('Geocode was not successful for the following reason: ' + status);
                    }
                });
    
                function getDistanceFromLatLonInKm(lolatitude1, lolongitude1, lolatitude2, lolongitude2) {
                    var R = 6371; // Radius of the earth in km
                    var dLat = deg2rad(window.lolatitude2 - window.lolatitude1); // deg2rad below
                    var dLon = deg2rad(window.lolongitude2 - window.lolongitude1);
                    var a =
                        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                        Math.cos(deg2rad(window.lolatitude1)) * Math.cos(deg2rad(window.lolatitude2)) *
                        Math.sin(dLon / 2) * Math.sin(dLon / 2);
                    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
                    var d = R * c; // Distance in km
                    return d.toLocaleString();
                }
    
                function deg2rad(deg) {
                    return deg * (Math.PI / 180)
                }
                var flightPlanCoordinates = [{
                        lat: window.lolatitude1,
                        lng: window.lolongitude1
                    }, {
                        lat: window.lolatitude2,
                        lng: window.lolongitude2
                    }
    
                ];
                var flightPath = new google.maps.Polyline({
                    path: flightPlanCoordinates,
                    geodesic: true,
                    strokeColor: '#FF0000',
                    strokeOpacity: 1.0,
                    strokeWeight: 2
                });
    
                flightPath.setMap(newmap1);
    
            }
    
        });
    });

     

    Output

    Google Maps Integration using API Key in UI5

  • Google Analytics Integration in SAP UI5

    Introduction

    There are multiple ways to trace page views and user activity. Among them, SAP provides SAP Analytics Cloud (SAC). Google Analytics is another way that can be integrated with SAP UI5. In this article, we will learn Google Analytics Integration in SAP UI5.

    What is Google Analytics

    Google Analytics is a web analytics service offered by Google that helps website owners and marketers understand how users interact with their websites and mobile apps. It provides detailed insights into user behavior, including page views, clicks, bounce rates, session duration, and more. With Google Analytics, website owners can measure the performance of their website, identify areas for improvement, and make data-driven decisions to optimize their online presence.

    Google Analytics works by placing a small piece of tracking code on the website, which collects data about user behavior and sends it to Google’s servers for analysis. The service offers a wide range of features and tools, including customizable reports, real-time data, audience segmentation, goal tracking, and more. It is widely used by businesses of all sizes and industries to improve their online marketing strategies, optimize their website performance, and drive conversions.

    How to configure Google Analytics

    To configure Google Analytics so that you can integrate it later with SAPUI5, you can follow these steps:

    1. Sign up for a Google Analytics account if you don’t already have one.
    2. Once you’re logged in, click on the Admin button in the lower left corner of the screen.
    3. In the Admin panel, click on the “Create Property” button to create a new property for your website.
    4. Follow the prompts to enter information about your website, such as the website name, URL, and time zone.
    5. On the next screen, select “Website” as the type of property and enter your website’s URL.
    6. Under “Advanced Options,” make sure that the “Create a Universal Analytics property” option is selected. This will enable you to use the latest version of Google Analytics, which supports more advanced features and reporting.
    7. Follow the remaining prompts to complete the setup process and obtain your tracking ID. This ID will be in the format “UA-XXXXX-Y” where “XXXXX” represents your account number and “Y” represents the property number.
    8. Once you have your tracking ID, you can integrate Google Analytics with SAPUI5 by adding the tracking code to your application, as described in the previous answer. Make sure to replace “GA_MEASUREMENT_ID” with your actual tracking ID.

    How to Integrate Google Analytics in SAP UI5

    To implement Google Analytics tracking using SAPUI5, you can follow these steps:

    1. Add the Google Analytics tracking code to your SAPUI5 application. You can do this by creating a new JavaScript file and adding the tracking code to it. Make sure to replace “GA_MEASUREMENT_ID” with your actual tracking ID.
      sap.ui.define([], function() {
        "use strict";
        return {
          trackPageView: function() {
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', 'GA_MEASUREMENT_ID');
          },
          trackEvent: function(category, action, label, value) {
            window.gtag('event', action, {
              'event_category': category,
              'event_label': label,
              'value': value
            });
          }
        };
      });
      

       

    2. Include the JavaScript file in your SAPUI5 application by adding it to the manifest.json file.
      {
        "sap.ui5": {
          "resources": {
            "js": [{
              "uri": "path/to/tracking.js"
            }]
          }
        }
      }
      

       

    3. Call the trackPageView method in your SAPUI5 application’s controller or component.
      sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "path/to/tracking"
      ], function(Controller, tracking) {
        "use strict";
        return Controller.extend("your.namespace.controller.App", {
          onInit: function() {
            tracking.trackPageView();
          }
        });
      });
      

       

    4. Call the trackEvent method to track specific user actions in your SAPUI5 application.
      sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "path/to/tracking"
      ], function(Controller, tracking) {
        "use strict";
        return Controller.extend("your.namespace.controller.App", {
          onPressButton: function() {
            tracking.trackEvent("Button", "Click", "Submit", 1);
          }
        });
      });
      

       

      That’s it! With these steps, you can implement Google Analytics tracking in your SAPUI5 application and start collecting valuable data about your users’ actions.

       

    Google Analytics Integration in SAP UI5

    Index.html

    <script src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXX-Y"></script>

    Tracking.js

    sap.ui.define([], function() {
      "use strict";
      return {
        trackPageView: function() {
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config', 'UA-63143188-5');
        },
        trackEvent: function(category, action, label, value) {
          window.gtag('event', action, {
            'event_category': category,
            'event_label': label,
            'value': value
          });
        }
      };
    });

     

    Main.view

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:ndc="sap.ndc" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m"
        xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Google Analytics Integration in SAP UI5">
                        <content>
                            <Button icon="sap-icon://area-chart" text="Track Page View using Google Analytics" press="onPressButton"/>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

    Main.controller

    sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "sap/m/MessageBox",
        "sap/m/MessageToast",
        "sap/ui/model/json/JSONModel",
        "Test/Test/js/tracking"
    
    ], function (Controller, MessageBox, MessageToast, JSONModel, tracking) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onInit: function () {
                
            },
    
            onPressButton: function () {
                tracking.trackPageView();
            }
        });
    });

    Manifest.json

            "resources": {
                "js": [{
                    "uri": "js/tracking.js"
                }]
    }

    Output

    Google Analytics Integration in SAP UI5

    Google Analytics

    Before

    Google Analytics Before Integration in SAP UI5

    After

    Google Analytics After Integration in SAP UI5

  • Encrypting Data in SAP UI5 using SHA256

    Introduction

    After implementing hashing via AES 256 (read here), one can conclude that since we can hash and unhash data, hence the encrypted data can be decrypted anyhow, and our data can be stolen. In a special scenario, where you don’t need decryption and just need hashing of data, we use SHA256 Encryption. It has a very important role in Blockchain. In this article, we will learn Encrypting Data in SAP UI5 using SHA256.

    What is SHA 256?

    The full form of SHA is the Secure Hash Algorithm, and SHA 256 is part of the series SHA Encryption. SHA256 always give result in the form of 256 characters for any type of input.

    Can we decrypt the data of SHA 256?

    SHA 256 are one-way of encryption, and the encrypted values cannot be decrypted. In case you find some online portals decrypting your hash, then it would mean that they have saved some hashes in their db and just returning the values that they have saved with it.

    How to Implement Encryption in SAP UI5 using SHA256

    To implement SHA 256 in SAP UI5, you need to include the given scripts in Index.html

    <script src=”https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/core.min.js”></script>
    <script src=”https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/sha256.js”></script>

    Index.html

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <!--<meta name="viewport" content="width=device-width, initial-scale=1.0">-->
            <title>My Project Ideas</title>
             <link rel="icon" type="image/x-icon" href="https://myprojectideas.com/wp-content/uploads/2021/08/cropped-Screenshot-2021-07-26-at-1.39.04-PM-32x32.png">
            <script id="sap-ui-bootstrap"
                src="resources/sap-ui-core.js"
                data-sap-ui-theme="sap_fiori_3"
                data-sap-ui-resourceroots='{"Test.Test": "./"}'
                data-sap-ui-compatVersion="edge"
                data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
                data-sap-ui-async="true"
                data-sap-ui-frameOptions="trusted">
            </script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/core.min.js"></script>
        	<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/sha256.js"></script>
        </head>
        <body class="sapUiBody">
            <div data-sap-ui-component data-name="Test.Test" data-id="container" data-settings='{"id" : "Test"}'></div>
        </body>
    </html>

    View.xml

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:ndc="sap.ndc" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m"
        xmlns:core="sap.ui.core" xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Encrypting Data in SAP UI5 using SHA256">
                        <content>
                            <VBox>
                                <Text text="Enter your text for SHA Encryption"/>
                                <Input id="idText"/>
                                <Button text="Encrypt" press="onPressEncrypt"/>
                                <Text text="Encrypted Text"/>
                                <Input editable="false" id="idEncrypted"/>
                                <Title text="Verify Hash"/>
                                <Input id="idTextVerify"/>
                                <Button id="idButtonVerify" enabled="false" text="Verify" press="onPressVerify"/>
                                <Input editable="false" id="idNewhHash"/>
                                <Text id="idStatus" text=""/>
                            </VBox>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

     

    Controller.js

    sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "sap/m/MessageBox",
        "sap/m/MessageToast",
        "sap/ui/model/json/JSONModel",
        "sap/ndc/BarcodeScanner"
    
    ], function (Controller, MessageBox, MessageToast, JSONModel, BarcodeScanner) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onPressEncrypt: function (oEvent) {
                var text = this.byId("idText").getValue();
                var payload = this.encrypt(text);
                this.byId("idButtonVerify").setEnabled(true);
                this.byId("idTextVerify").setEnabled(true);
                this.byId("idEncrypted").setValue(payload);
            },
    
            onPressVerify: function (oEvent) {
                var text = this.byId("idTextVerify").getValue();
                var payload = this.encrypt(text);
                this.byId("idNewhHash").setValue(payload);
                var oldHash = this.byId("idEncrypted").getValue();
                var newHash = this.byId("idNewhHash").getValue();
                if (newHash === oldHash) {
                    this.byId("idStatus").setText("Hash is same!");
                } else {
                    this.byId("idStatus").setText("Hash is different!");
                }
            },
    
            encrypt: function (input) {
                var passhash = CryptoJS.SHA256(input);
                return passhash;
            }
    
        });
    });

     

    Output

    Success

    Encrypting Data in SAP UI5 using SHA256

    Error

    Encrypting Data in SAP UI5 using SHA256 Mismatch

  • PHP & SQL Integration in SAP UI5

    Introduction

    We can use SAP UI5 and integrate it with any backend technologies available in the market. In this article, we will learn simple steps related to PHP & SQL Integration in SAP UI5.

    How to Integrate PHP & SQL with SAP UI5

    To Integrate PHP & SQL with SAP UI5, follow this simple flow:

    Steps to follow for PHP

    • Install XAMPP
    • Run PHP My Admin (to see database): http://localhost:80/phpmyadmin/
    • Create a db with a few tables
    • Create a notepad file, save it as process.php
    • Add these configurations:
      • $servername = “localhost”;
      • $username = “root”;
      • $dbname = “<your db name>”;
    • Add these line to start connection:
      • $conn = new mysqli($servername, $username,””, $dbname);
      • if ($conn->connect_error) {
      • die(“Connection failed: ” . $conn->connect_error);
    • At the top of php file, add:
      • header(“Access-Control-Allow-Origin:*”);
      • echo $_POST[“method”]();

    How to Connect a PHP File with SQL

    Steps to Integrate PHP & SQL in SAP UI5

    Step 01: Download, Install, and Run XAMPP

    XAMPP for SAP UI5

    Step 02: Once the server is up and running, open up php my admin using this URL: http://localhost:80/phpmyadmin/

    Step 03: Create a database and few tables within it

    Step 04: Create a PHP file, do the configuration of SQL connection as mentioned above and then save it within htdocs folder, preferably plan to save it within the UI5 folder

    Step 05: Within the PHP file, write CRUD operation code within different functions. Learn PHP coding here.

    Step 06: Configure PHP with UI5, as discuss in upcoming section

    Step 07: Write code in UI5 to perform CRUD Operation

    Step 08: Download the zip of UI5 folder and save with the htdocs folder. Now, you can run your code without the internet, just using XAMPP. And you data would be saved with the SQL table.

    How to Connect UI5 with PHP file

    To connect UI5 with PHP, you just need to provide the URL pointing to the PHP file. In our use case, we have stored the PHP file in the default location provided by the XAMPP server i.e., htdocs. Within that folder, we have our UI5 App i.e. Hisab; within that, we have a folder for PHP by the name php where we have saved our php file by the name process.php.
    Hence the URL pointing the same will be: http://localhost:80/Hisab/php/process.php

    And the code in UI5 will be:

    this.http = "http://";
    this.uri = this.http + "localhost:80/Hisab/php/process.php";

     

    How to perform CRUD operation from UI5 using PHP in SQL Database

    We will use AJAX call to call our code in the PHP file.

    PHP file: process.php

    <?php 
    header("Access-Control-Allow-Origin:*");
    // header('Content-Type: application/json');
    echo $_POST["method"]();
    
    function getClientTransaction(){
    $servername = "localhost";
    $username = "root";
    $dbname = "hisabkitab";
    // Create connection
    $conn = new mysqli($servername, $username,"", $dbname);
    // Check connection
        if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
        }
    // Get Filters
        $obj = json_decode($_POST["data"]);
        $Client = $obj->Client;
        $month = $obj->month;
        $year = $obj->year;
        $machineType = $obj->machineType;
        $officeType = $obj->officeType;
        $machineClause = "machineType = '".$machineType."'";
        $officeClause = "cc = '".$officeType."'";
        $clientClause = "client = '".$Client."'";
        if($machineType == "All")
        {
            $machineClause = "machineType != ''";
        }
        if($officeType == "All")
        {
            $officeClause = "cc != ''";
        }
        if($Client == "All")
        {
            $clientClause = "client != ''";
        }
    
        if ($result = $conn -> query("SELECT * FROM transaction WHERE ".$machineClause." AND ".$officeClause." AND ".$clientClause." AND month = '{$month}' AND year = '{$year}' ORDER by date DESC")) {
            if($result->num_rows > 0) {
                $i = 0;
                while($row = $result->fetch_assoc()){
                    $dataArray[$i] = $row;
                    $i = $i + 1;
                }
                echo json_encode($dataArray);
            }
        }
    }
    
    function onCreateATransaction(){
    $servername = "localhost";
    $username = "root";
    $dbname = "hisabkitab";
    // Create connection
    $conn = new mysqli($servername, $username,"", $dbname);
    // Check connection
        if ($conn->connect_error) {
        die("Connection failed: " . $conn->connect_error);
        }
        $timestamp = date('Y-m-d H:i:s');
        $obj = json_decode($_POST["data"]);
        $client = $obj->client;
        $labour = $obj->labour;
        $date = $obj->date;
        $time=strtotime($date);
        $month = $obj->month;
        $year=$obj->year;
        $cc = $obj->cc;
        $rate = $obj->rate;
        $quantity = $obj->quantity;
        $machineType = $obj->machineType;
        $total = $obj->total;
        $sql = "INSERT INTO transaction(date,client,labour,cc,rate,quantity,machineType,total, month, year) VALUES ('$date','$client','$labour','$cc','$rate','$quantity','$machineType','$total','$month','$year')";
        if(mysqli_query($conn,$sql)){
        $dataArray[0] = 'Insertion successful';
        echo json_encode($dataArray);
        }
        else{
        $dataArray[0] = 'Insertion failed';
        echo json_encode($dataArray);
        }
    }
    ?>

    View Code

    1. Create Transaction

    <mvc:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="Hisab.Hisab.controller.TransactionShaving"
        xmlns:html="http://www.w3.org/1999/xhtml">
        <Page title="Create a new Shaving Transaction" showNavButton="true" navButtonPress="onpressBack" titleAlignment="Center">
            <content>
                <HBox class="sapUiSmallMargin">
                    <VBox class="sapUiSmallMarginEnd">
                        <Label text="Select Office" design="Bold" required="true"/>
                        <ComboBox id="idOffice" >
                            <core:Item key="Main Office" text="Main Office"/>
                            <core:Item key="Nauri Ram" text="Nauri Ram"/>
                            <core:Item key="Maidan" text="Maidan"/>
                        </ComboBox>
                    </VBox>
                    <VBox class="sapUiSmallMarginEnd">
                        <Label text="Enter the Labour Name" design="Bold" required="true"/>
                        <ComboBox id="idLabor" items="{ComboModel>/Labour_results}" change="onChangeCountry">
                            <items>
                                <core:Item key="{ComboModel>Labor}" text="{ComboModel>Labor}"/>
                            </items>
                        </ComboBox>
                    </VBox>
                </HBox>
                <VBox id="idcTxBox" class="sapUiMediumMarginEnd">
                    <!--Table to get User Inputs-->
                    <Table id="idTable" headerText="Add Records" sticky="ColumnHeaders" growing="true" growingThreshold="10" class="sapUiSizeCompact"
                        >
                        <headerToolbar>
                            <OverflowToolbar design="Transparent">
                                <Title text="Add Records"/>
                                <ToolbarSpacer/>
                                <!-- <Button text="Add New" icon="sap-icon://add" tooltip="Add New" press="onAddRow"/> -->
                                <!-- <Button text="Submit" icon="sap-icon://refresh" tooltip="Refresh" press="onSaveTransaction"/> -->
                            </OverflowToolbar>
                        </headerToolbar>
                        <columns>
                            <Column  hAlign="Left">
                                <Label text="Date" required="true"/>
                            </Column>
                            <Column hAlign="Left">
                                <Label text="Client" required="true"/>
                            </Column>
                            <Column hAlign="Left">
                                <Label text="Quantity" required="true"/>
                            </Column>
                            <Column hAlign="Left">
                                <Label text="Rate" required="true"/>
                            </Column>
                            <Column  hAlign="Left">
                                <!-- <Label text="Rate" required="true"/> -->
                            </Column>
                        </columns>
                        <items>
                            <ColumnListItem>
                                <cells>
                                    <DatePicker id="datePicker" displayFormat="dd-MM-yyyy" valueFormat="dd/MM/yyyy" value="{/Date}" />
                                    <Input  value="{/Client}" placeholder="Enter Client Name" showSuggestion="true" suggestionItems="{ComboModel>/Clients_results}">
                                        <suggestionItems>
                                            <core:Item text="{ComboModel>client}"/>
                                        </suggestionItems>
                                    </Input>
                                    <Input  value="{/Quantity}" type="Number" submit="onSumbit"/>
                                    <Input  value="{/Rate}" type="Number" submit="onSumbit"/>
                                    <!-- <Input value="{Rate}" type="Number" submit="onSumbit"/> -->
                                    <Button type="Accept" text="{i18n>Submit}" press="onSaveTransaction"/>
                                </cells>
                            </ColumnListItem>
                        </items>
                    </Table>
                </VBox>
            </content>
        </Page>
    </mvc:View>

     

    2. View Transaction

    <mvc:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="Hisab.Hisab.controller.ViewTransaction"
        xmlns:html="http://www.w3.org/1999/xhtml">
        <Page title="View Transactions" showNavButton="true" navButtonPress="onpressBack" titleAlignment="Center">
            <content>
                <HBox class="sapUiSmallMargin">
                    <VBox class="sapUiSmallMarginEnd">
                        <Label text="Select Office" design="Bold" required="true"/>
                        <ComboBox id="idOffice" selectionChange="onChangeSelection" selectedKey="All">
                            <core:Item key="All" text="All"/>
                            <core:Item key="Main Office" text="Main Office"/>
                            <core:Item key="Nauri Ram" text="Nauri Ram"/>
                            <core:Item key="Maidan" text="Maidan"/>
                        </ComboBox>
                    </VBox>
                    <VBox class="sapUiSmallMarginEnd">
                        <Label text="Select Client" design="Bold" required="true"/>
                        <ComboBox id="idClient" items="{ path: 'ComboModel>/Clients_results', sorter: { path: 'cc', descending: false, group: true } }">
                            <core:Item key="{ComboModel>client}" text="{ComboModel>client}"/>
                        </ComboBox>
                    </VBox>
                    <VBox class="sapUiSmallMarginEnd">
                        <Label text="Operation" design="Bold" required="true"/>
                        <ComboBox id="idOperation" selectionChange="onChangeSelection" selectedKey="All">
                            <core:Item key="All" text="All"/>
                            <core:Item key="Shaving" text="Shaving"/>
                            <core:Item key="Buffing" text="Buffing"/>
                            <core:Item key="Softening" text="Softening"/>
                            <core:Item key="Milling" text="Milling"/>
                            <core:Item key="Tangan" text="Tangan"/>
                            <core:Item key="Thokai" text="Thokai"/>
                        </ComboBox>
                    </VBox>
                    <VBox class="sapUiSmallMarginEnd">
                        <Label text="Select Month" design="Bold" required="true"/>
                        <ComboBox id="idMonth" selectionChange="onChangeSelection" selectedKey="01">
                            <core:Item key="01" text="January"/>
                            <core:Item key="02" text="February"/>
                            <core:Item key="03" text="March"/>
                            <core:Item key="04" text="April"/>
                            <core:Item key="05" text="May"/>
                            <core:Item key="06" text="June"/>
                            <core:Item key="07" text="July"/>
                            <core:Item key="08" text="August"/>
                            <core:Item key="09" text="September"/>
                            <core:Item key="10" text="October"/>
                            <core:Item key="11" text="November"/>
                            <core:Item key="12" text="December"/>
                        </ComboBox>
                    </VBox>
                    <VBox class="sapUiSmallMarginEnd">
                        <Label text="Select Year" design="Bold" required="true"/>
                        <ComboBox id="idYear" selectionChange="onChangeSelection" selectedKey="2020">
                            <core:Item key="2020" text="2020"/>
                            <core:Item key="2021" text="2021"/>
                            <core:Item key="2022" text="2022"/>
                            <core:Item key="2022" text="2023"/>
                        </ComboBox>
                    </VBox>
                    <VBox>
                        <Label/>
                        <Button text="Get Transactions" press="onGetTransaction"/>
                    </VBox>
                </HBox>
                <VBox id="idClientTx" visible="false">
                    <VBox class="sapUiMediumMarginEnd">
                        <!-- Table to get User Inputs -->
                        <Table id="idTable" headerText="Client Transactions" sticky="ColumnHeaders" growing="true" mode="SingleSelectLeft" growingThreshold="20"
                            class="sapUiSizeCompact" items="{detailsModel>/results}">
                            <headerToolbar>
                                <OverflowToolbar>
                                    <Title id="idTableHeader" text="All Transactions" level="H2"/>
                                    <ToolbarSpacer/>
                                    <Button text="Delete" icon="sap-icon://delete" press="onDelete"/>
                                </OverflowToolbar>
                            </headerToolbar>
                            <columns>
                                <Column hAlign="Left">
                                    <Label text="Date"/>
                                </Column>
                                <Column hAlign="Left">
                                    <Label text="Office"/>
                                </Column>
                                <Column hAlign="Left">
                                    <Label text="Labour"/>
                                </Column>
                                <Column hAlign="Left">
                                    <Label text="Operation"/>
                                </Column>
                                <Column hAlign="Left">
                                    <Label text="Quantity/Hours"/>
                                </Column>
                                <Column hAlign="Left">
                                    <Label text="Rate"/>
                                </Column>
                                <Column hAlign="Left">
                                    <Label text="Amount"/>
                                </Column>
                            </columns>
                            <items>
                                <ColumnListItem type="Navigation" selected="onClickTransaction">
                                    <cells>
                                        <Text text="{detailsModel>date}"/>
                                        <Text text="{detailsModel>cc}"/>
                                        <Text text="{detailsModel>labour}"/>
                                        <Text text="{detailsModel>machineType}"/>
                                        <Text text="{detailsModel>quantity}"/>
                                        <Text text="{detailsModel>rate}"/>
                                        <Text text="{detailsModel>total}"/>
                                    </cells>
                                </ColumnListItem>
                            </items>
                        </Table>
                    </VBox>
                </VBox>
            </content>
        </Page>
    </mvc:View>

     

    Controller Code

    1. Create Transaction

    sap.ui.define(
      [
        "sap/ui/core/mvc/Controller",
        "sap/ui/model/json/JSONModel",
        "sap/m/MessageBox",
      ],
      function (Controller, JSONModel, MessageBox) {
        "use strict";
    
        return Controller.extend("Hisab.Hisab.controller.TransactionShaving", {
          /**
           * Called when a controller is instantiated and its View controls (if available) are already created.
           * Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
           * @memberOf Hisab.Hisab.view.TransactionShaving
           */
          onInit: function () {
            this.oRouter = sap.ui.core.UIComponent.getRouterFor(this);
            this.http = "http://";
            this.uri = this.http + "localhost:81/Hisab/php/process.php";
            this.oRouter
              .getRoute("TransactionShaving")
              .attachPatternMatched(this._handleRouteMatched, this);
          },
    
          _handleRouteMatched: function (oEvent) {
            this.updateValues();
            // get First Row
            this.getFirstRow();
          },
    
          onpressBack: function (oEvent) {
            this.oRouter.navTo("Main");
          },
          updateValues: function () {
            var that = this;
            // Get Labour's Data
            $.ajax({
              url: this.uri,
              type: "POST",
              data: {
                method: "getAllLabours",
                data: JSON.stringify({}),
              },
              dataType: "json",
              success: function (dataLabour) {
                // Get Labour's Data
                $.ajax({
                  url: that.uri,
                  type: "POST",
                  data: {
                    method: "getAllClients",
                    data: JSON.stringify({}),
                  },
                  dataType: "json",
                  success: function (dataClient) {
                    that.ClientList = [];
                    var ComboObj = {
                      Labour_results: dataLabour,
                      Clients_results: dataClient,
                    };
                    dataClient.forEach(function (Client) {
                      that.ClientList.push(Client.Client);
                    });
                    that.getView().setModel(new JSONModel(ComboObj), "ComboModel");
                  },
                  error: function (request, error) {},
                });
              },
              error: function (request, error) {},
            });
          },
          getFirstRow: function (oEvent) {
            // Empty Model
            var data = {
              Date: "",
              Client: "",
              Quantity: "",
              Rate: "",
            };
            // Add Data
            var oModel = new sap.ui.model.json.JSONModel(data);
            // Set Model
            this.byId("idTable").setModel(oModel);
          },
    
          onAddRow: function (oEvent) {
            var flag = true;
            var tableData = this.byId("idTable").getModel().getData();
            tableData.results.forEach(function (temp) {
              if (!temp.Date && !temp.Client && !temp.Quantity && !temp.Rate) {
                flag = false;
              }
            });
            if (flag === true) {
              var cuurentModel = this.byId("idTable").getModel().getData().results;
              cuurentModel.push({
                Date: "",
                Client: "",
                Quantity: "",
                Rate: "",
              });
              this.byId("idTable").getModel().refresh();
            } else {
              MessageBox.error("All fields are mandatory!");
            }
          },
          onRefresh: function () {
            this.byId("idTable").getModel().setData({
              Date: "",
              Client: "",
              Quantity: "",
              Rate: "",
            });
            this.byId("idTable").getModel().refresh();
          },
          onSaveTransaction: function () {
            var that = this;
            var sLaborName = this.byId("idLabor").getValue();
            var sOffice = this.byId("idOffice").getSelectedKey();
            if (sOffice && sLaborName) {
              var temp = this.byId("idTable").getModel().getData();
              if (!temp.Date || !temp.Client || !temp.Quantity || !temp.Rate) {
                alert("Fill all details");
              } else {
                var dataLabor = {
                  id: sLaborName.toLowerCase().replace(/ /g, ""),
                  Labor: sLaborName,
                };
                $.ajax({
                  url: that.uri,
                  type: "POST",
                  data: {
                    method: "onCreateLabor",
                    data: JSON.stringify(dataLabor),
                  },
                  dataType: "json",
                  success: function (dataClient) {
                    console.log("success");
                  },
                  error: function (request, error) {
                    console.log(error);
                  },
                });
                var data = JSON.stringify({
                  client: temp.Client,
                  labour: sLaborName,
                  date: temp.Date,
                  month: parseInt(temp.Date.substring(3, 5), 0),
                  cc: sOffice,
                  rate: temp.Rate,
                  quantity: temp.Quantity,
                  machineType: "Shaving",
                  total: temp.Rate * temp.Quantity,
                  year: parseInt(temp.Date.substring(6), 0),
                });
                $.ajax({
                  url: that.uri,
                  type: "POST",
                  data: {
                    method: "onCreateATransaction",
                    data: data,
                  },
                  crossDomain: true,
                  dataType: "json",
                  success: function (sData) {
                    var messages = sData[0] + "\n";
                    // that.onRefresh();
                    that.getView().byId("datePicker").focus();
                    that.updateValues();
                    // that._handleRouteMatched();
                    // MessageBox.success(messages);
                  },
                  error: function (request, error) {
                    MessageBox.error(request.responseText);
                    // if (i === results.length && messages.length > 0) {
                    //   MessageBox.success(messages);
                    //   that._handleRouteMatched();
                    // }
                  },
                });
                that.saveClient(temp.Client);
              }
            } else {
              alert("Labor ka naam nhi hai");
            }
          },
         
    
          onResetTransaction: function (oEvent) {
            this.getFirstRow();
            this._handleRouteMatched();
          },
    
          saveClient: function (client) {
            var that = this;
            var dataClient = {
              id: client.toLowerCase().replace(/ /g, ""),
              Client: client,
            };
            // Save Labour's Data
            $.ajax({
              url: that.uri,
              type: "POST",
              data: {
                method: "onCreateClient",
                data: JSON.stringify(dataClient),
              },
              dataType: "json",
              success: function (success) {},
              error: function (request, error) {},
            });
          },
        });
      }
    );
    

     

    2. View Transaction

    sap.ui.define([
            "sap/ui/core/mvc/Controller",
            "sap/ui/model/json/JSONModel"
        ],
        function (Controller, JSONModel) {
            "use strict";
    
            return Controller.extend("Hisab.Hisab.controller.ViewTransaction", {
                /**
                 * Called when a controller is instantiated and its View controls (if available) are already created.
                 * Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
                 * @memberOf Hisab.Hisab.view.ClientPayment
                 */
                onInit: function () {
                    this.oRouter = sap.ui.core.UIComponent.getRouterFor(this);
                    this.http = "http://";
                    this.uri = this.http + "localhost:81/Hisab/php/process.php";
                    this.oRouter.getRoute("ViewTransaction").attachPatternMatched(this._handleRouteMatched, this);
                    this.getView().byId("idMonth").setSelectedKey(new Date().getMonth().toString());
                },
    
                _handleRouteMatched: function (oEvent) {
                    var that = this;
                    $.ajax({
                        url: that.uri,
                        type: "POST",
                        data: {
                            method: "getAllClients",
                            data: JSON.stringify({}),
                        },
                        dataType: "json",
                        success: function (dataClient) {
                            var data = [{
                                id: "All",
                                client: "All"
                            }];
                            data = data.concat(dataClient);
                            var ComboObj = {
                                Clients_results: data,
                            };
                            that.getView().setModel(new JSONModel(ComboObj), "ComboModel");
                        },
                        error: function (request, error) {
                            // console.log("fhfj");
                        },
                    });
                },
    
                onpressBack: function (oEvent) {
                    this.oRouter.navTo("Main");
                },
                onChangeSelection: function () {
                    var that = this;
                    var data = {};
                    this.byId("idClient").setSelectedKey("");
                    data.month = this.byId("idMonth").getSelectedKey();
                    data.year = this.byId("idYear").getSelectedKey();
                    data.machineType = this.byId("idOperation").getSelectedKey();
                    data.officeType = this.byId("idOffice").getSelectedKey();
                    $.ajax({
                        url: that.uri,
                        type: "POST",
                        data: {
                            method: "getAllClientsWithParam",
                            data: JSON.stringify(data),
                        },
                        dataType: "json",
                        success: function (dataClient) {
                            var data = [{
                                id: "All",
                                client: "All"
                            }];
                            data = data.concat(dataClient);
                            var ComboObj = {
                                Clients_results: data,
                            };
                            that.getView().setModel(new JSONModel(ComboObj), "ComboModel");
                        },
                        error: function (request, error) {
                            // console.log("fhfj");
                            var ComboObj = {
                                Clients_results: [],
                            };
                            that.getView().setModel(new JSONModel(ComboObj), "ComboModel");
                        },
                    });
                },
    
                onGetTransaction: function (oEvent) {
                    var that = this;
                    this.byId("idClientTx").setVisible(true);
                    var Client = this.byId("idClient").getSelectedKey();
                    var month = this.byId("idMonth").getSelectedKey();
                    var year = this.byId("idYear").getSelectedKey();
                    var machineType = this.byId("idOperation").getSelectedKey();
                    var officeType = this.byId("idOffice").getSelectedKey();
    
                    var data = {
                        Client: Client,
                        month: month,
                        year: year,
                        machineType: machineType,
                        officeType: officeType,
                    };
                    $.ajax({
                        url: that.uri,
                        type: "POST",
                        data: {
                            method: "getClientTransaction",
                            data: JSON.stringify(data),
                        },
                        dataType: "json",
                        success: function (dataClient) {
                            var detailsModel = {
                                results: dataClient
                            };
                            var sum = 0;
                            var count = dataClient.length;
                            dataClient.forEach(function (amount) {
                                sum = sum + parseInt(amount.total, 0);
                            });
                            that
                                .byId("idTableHeader")
                                .setText("All Transactions (" + count + ")");
                            that
                                .getView()
                                .byId("idTable")
                                .setModel(new JSONModel(detailsModel), "detailsModel");
                        },
                        error: function (request, error) {
                            that
                                .getView()
                                .byId("idTable")
                                .setModel(new JSONModel({
                                    results: []
                                }), "detailsModel");
                            that.byId("idTableHeader")
                                .setText("All Transactions (0)");
                        }
                    });
                },
    
                onResetTransaction: function (oEvent) {
                    this.byId("idClientTx").setVisible(false);
                }
            });
        });

    Output

    1. Create Transaction

    Create a transaction using PHP in SAP UI5

    2. View Transaction

    View a transaction using PHP in SAP UI5

  • Create a Simple Chat bot in SAP UI5

    Introduction

    A chatbot is an important function and has become part of all front-end applications nowadays. In this article, we will Create a Simple Chat bot in SAP UI5.

    What is Chat Bot?

    A Chat Bot is an application via which any person can interact with a system or computer. The answers generated by the computers may be hardcoded based on the questions or can be real-time generated with the help of Artificial intelligence.

    How to Implement Chatbot in SAP UI5?

    In this article, we will develop a simple chat bot where the answers are hardcoded in the UI itself. You can always replace those responses by sending the inputs to your APIs and showing the result of the APIs as output.

    Steps to Create a Simple Chat Bot in SAP UI5

    Steps to Create a Simple Chat bot in SAP UI5

    Flow of Chat Bot

    Flow of Chat Bot

    View.xml

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
        xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Simple Chat Bot using SAP UI5">
                        <content></content>
                        <footer>
                            <OverflowToolbar>
                                <ToolbarSpacer/>
                                <Button text="Click to Chat" icon="sap-icon://message-popup" press="handleMessagePopoverPress"/>
                            </OverflowToolbar>
                        </footer>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

     

    Controller.js

    sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "sap/m/MessageBox",
        "sap/m/MessageToast",
        "sap/ui/model/json/JSONModel"
    
    ], function (Controller, MessageBox, MessageToast, JSONModel) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
    
            handleMessagePopoverPress: function (oEvent) {
    
                // create popover
                if (!this._oPopover) {
                    this._oPopover = sap.ui.xmlfragment("Test.Test.fragment.Bot", this);
                    this.getView().addDependent(this._oPopover);
                }
                if (this._oPopover.isOpen()) {
                    this._oPopover.close();
                } else {
                    this._oPopover.openBy(oEvent.getSource());
                }
            },
            ask: function (oEvent) {
                var input = sap.ui.getCore().byId("query").getValue();
                var fBox = new sap.m.FlexBox({
                    alignItems: "Start",
                    justifyContent: "End"
                });
                var text = new sap.m.Text({
                    text: input
                });
                text.addStyleClass("chat2");
                fBox.addItem(text);
                fBox.addStyleClass("sapUiSmallMarginTop");
                sap.ui.getCore().byId("chat").addItem(fBox);
                sap.ui.getCore().byId("query").setValue("");
                this.answer(input);
            },
            answer: function (query) {
                var greetings = ["hi", "hello", "what's up", "wassup"];
                var greetings_response = ["Hello", "Nice to meet you", "Hmm mm"];
                var job = ["what can you do for me?", "what can you do for me", "what can you do", "what can you do?"];
                if (query) {
                    if (greetings.indexOf(query.toLowerCase()) != -1) {
                        var item = greetings_response[Math.floor(Math.random() * greetings_response.length)];
                        var a = this.createText(item);
                        this.reply(a);
                    } else if (query.toLowerCase().match(/what.*you.*do/g)) {
                        var a = this.createText("What do you want me to do? XD");
                        var b = this.createButton("Show you your Questionnaire");
                        var c = this.createButton("Show you user details");
                        var d = this.createButton("Delete users");
                        var e = this.createButton("Do something naughty");
                        var vbox = new sap.m.VBox();
                        vbox.addItem(a);
                        vbox.addItem(b);
                        vbox.addItem(c);
                        vbox.addItem(d);
                        vbox.addItem(e);
    
                        this.reply(vbox);
                    } else {
                        this.reply();
                    }
                }
            },
            reply: function (ans) {
                if (ans) {
                    var fBox = new sap.m.FlexBox({
                        alignItems: "Start",
                        justifyContent: "Start"
                    });
                    ans.addStyleClass("chat1");
                    ans.addStyleClass("sapUiSizeCompact");
                    fBox.addItem(ans);
                    fBox.addStyleClass("sapUiSmallMarginTop");
                    sap.ui.getCore().byId("chat").addItem(fBox);
                } else {
                    var fBox = new sap.m.FlexBox({
                        alignItems: "Start",
                        justifyContent: "Start"
                    });
                    var text = new sap.m.Text({
                        text: "Did not recognize you. Come again"
                    });
                    text.addStyleClass("chat1");
                    fBox.addItem(text);
                    fBox.addStyleClass("sapUiSmallMarginTop");
                    sap.ui.getCore().byId("chat").addItem(fBox);
                }
                $("#pop-cont").scrollTop($("#pop-cont")[0].scrollHeight - $("#pop-cont").height());
    
            },
            onClear: function (oEvent) {
                sap.ui.getCore().byId("chat").removeAllItems();
            },
    
            onScroll: function () {
                $("#pop-cont").scrollTop($("#pop-cont")[0].scrollHeight - $("#pop-cont").height());
            },
    
            createText: function (text) {
                var text = new sap.m.Text({
                    text: text
                });
                return text;
            },
            buttonPress: function (btext) {
                var that = this;
                var naughty = ["I just did.\n I was being naughty by giving you the option of being naughty :D", "You should not ask for that ;)",
                    "Its rude to ask for it", "Gotcha :P ", "That was a character test, you failed"
                ];
                var btext = btext.toLowerCase();
                if (btext.match(/show.*ques/g)) {
                    var Input = new sap.m.Input({
                        submit: function (oEvent) {
                            that.onTestPress(oEvent, oEvent.getParameter("value"));
                        }
                    });
                    var a = this.createText("Provide the SET NAME-SET ID  and hit Enter");
                    var vbox = new sap.m.VBox();
                    vbox.addItem(a);
                    vbox.addItem(Input);
                    this.reply(vbox);
                } else if (btext.match(/show.*user/g)) {
                    var Input = new sap.m.Input({
                        submit: function (oEvent) {
                            that.onUserPress(oEvent, oEvent.getParameter("value"));
                        }
                    });
                    var a = this.createText("Provide the USER_ID  and hit Enter");
                    var vbox = new sap.m.VBox();
                    vbox.addItem(a);
                    vbox.addItem(Input);
                    this.reply(vbox);
                } else if (btext.match(/delete.*user/g)) {
                    var a = this.createText("Sorry the function is not yet available");
                    this.reply(a);
                } else if (btext.match(/naughty/g)) {
                    var item = naughty[Math.floor(Math.random() * naughty.length)];
                    var a = this.createText(item);
                    this.reply(a);
                }
            },
            createButton: function (text) {
                var that = this;
                var link = new sap.m.Button({
                    text: text,
                    type: sap.m.ButtonType.Accept,
                    press: function (oEvent) {
                        that.buttonPress(text);
                    }
                });
                link.addStyleClass("sapUiSmallMarginTop");
                return link;
            },
    
        });
    });

     

    Bot.fragment.xml

    <core:FragmentDefinition id="fragment23" xmlns="sap.m" xmlns:core="sap.ui.core">
        <Popover id="pop" title="Welcome to UI5 Chat Bot" class="sapUiContentPadding" resizable="true" verticalScrolling="true" contentHeight="200px"
            placement="Top" initialFocus="query">
            <footer>
                <Toolbar>
                    <ToolbarSpacer/>
                    <Input submit="ask" id="query" type="text" width="200px" value="" class="sapUiSmallMargin"/>
                    <Button text="Clear" press="onClear"/>
                </Toolbar>
            </footer>
            <VBox id="chat">
                <FlexBox class="sapUiSmallMarginTop" alignItems="Start" justifyContent="Start">
                    <items>
                        <Text class="chat1" text="How may I help you?"/>
                    </items>
                </FlexBox>
            </VBox>
        </Popover>
    </core:FragmentDefinition>

    Output

    Simple Chat Bot using SAP UI5

  • Encrypting and Decrypting Data in SAP UI5 using aes.js

    Introduction

    In this article, we will go through the encryption and decryption of any data in SAP UI5 using Aes.js

    What is Encryption

    Encryption is a methodology to convert data that can be hacked into another unreadable format. In this way, only the right user can convert the data back into readable format.

    How to Encrypt and Decrypt data using Aes.js

    To encrypt and decrypt data using Aes.js, you can use two way:

    1. Implementing Aes.js using NodeJs
    2. Implementing Aes.js using cdn

    To implement Aes.js encryption and decryption in SAP UI5, we use CDN and add it to the index.html file.

    Encrypting and Decrypting Data in SAP UI5 using aes.js

    Encrypting and Decrypting Data in SAP UI5 using aes

    Index.html

    Either Add CDN in the index.html file as shown below:

    <script type="text/javascript" src="https://cdn.rawgit.com/ricmoo/aes-js/e27b99df/index.js"></script>
    

    or Download the content from here https://cdn.jsdelivr.net/gh/ricmoo/aes-js@e27b99df/index.js

    and add it in a new file called as aesjs.js inside a folder js within webapp.

    /**
     * @Author: Rudramani Pandey
     * Purpose: External API for Encryption and Decryption
     * Modified: 16.04.2023
     */
    "use strict";
    
    (function (root) {
    
        function checkInt(value) {
            return (parseInt(value) === value);
        }
    
        function checkInts(arrayish) {
            if (!checkInt(arrayish.length)) {
                return false;
            }
    
            for (var i = 0; i < arrayish.length; i++) {
                if (!checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) {
                    return false;
                }
            }
    
            return true;
        }
    
        function coerceArray(arg, copy) {
    
            // ArrayBuffer view
            if (arg.buffer && ArrayBuffer.isView(arg) && arg.name === 'Uint8Array') {
    
                if (copy) {
                    if (arg.slice) {
                        arg = arg.slice();
                    } else {
                        arg = Array.prototype.slice.call(arg);
                    }
                }
    
                return arg;
            }
    
            // It's an array; check it is a valid representation of a byte
            if (Array.isArray(arg)) {
                if (!checkInts(arg)) {
                    throw new Error('Array contains invalid value: ' + arg);
                }
    
                return new Uint8Array(arg);
            }
    
            // Something else, but behaves like an array (maybe a Buffer? Arguments?)
            if (checkInt(arg.length) && checkInts(arg)) {
                return new Uint8Array(arg);
            }
    
            throw new Error('unsupported array-like object');
        }
    
        function createArray(length) {
            return new Uint8Array(length);
        }
    
        function copyArray(sourceArray, targetArray, targetStart, sourceStart, sourceEnd) {
            if (sourceStart != null || sourceEnd != null) {
                if (sourceArray.slice) {
                    sourceArray = sourceArray.slice(sourceStart, sourceEnd);
                } else {
                    sourceArray = Array.prototype.slice.call(sourceArray, sourceStart, sourceEnd);
                }
            }
            targetArray.set(sourceArray, targetStart);
        }
    
        var convertUtf8 = (function () {
            function toBytes(text) {
                var result = [],
                    i = 0;
                text = encodeURI(text);
                while (i < text.length) {
                    var c = text.charCodeAt(i++);
    
                    // if it is a % sign, encode the following 2 bytes as a hex value
                    if (c === 37) {
                        result.push(parseInt(text.substr(i, 2), 16))
                        i += 2;
    
                        // otherwise, just the actual byte
                    } else {
                        result.push(c)
                    }
                }
    
                return coerceArray(result);
            }
    
            function fromBytes(bytes) {
                var result = [],
                    i = 0;
    
                while (i < bytes.length) {
                    var c = bytes[i];
    
                    if (c < 128) {
                        result.push(String.fromCharCode(c));
                        i++;
                    } else if (c > 191 && c < 224) {
                        result.push(String.fromCharCode(((c & 0x1f) << 6) | (bytes[i + 1] & 0x3f)));
                        i += 2;
                    } else {
                        result.push(String.fromCharCode(((c & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f)));
                        i += 3;
                    }
                }
    
                return result.join('');
            }
    
            return {
                toBytes: toBytes,
                fromBytes: fromBytes,
            }
        })();
    
        var convertHex = (function () {
            function toBytes(text) {
                var result = [];
                for (var i = 0; i < text.length; i += 2) {
                    result.push(parseInt(text.substr(i, 2), 16));
                }
    
                return result;
            }
    
            // http://ixti.net/development/javascript/2011/11/11/base64-encodedecode-of-utf8-in-browser-with-js.html
            var Hex = '0123456789abcdef';
    
            function fromBytes(bytes) {
                var result = [];
                for (var i = 0; i < bytes.length; i++) {
                    var v = bytes[i];
                    result.push(Hex[(v & 0xf0) >> 4] + Hex[v & 0x0f]);
                }
                return result.join('');
            }
    
            return {
                toBytes: toBytes,
                fromBytes: fromBytes,
            }
        })();
    
        // Number of rounds by keysize
        var numberOfRounds = {
            16: 10,
            24: 12,
            32: 14
        }
    
        // Round constant words
        var rcon = [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97,
            0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
        ];
    
        // S-box and Inverse S-box (S is for Substitution)
        var S = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa,
            0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5,
            0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09,
            0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1,
            0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50,
            0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13,
            0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46,
            0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4,
            0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c,
            0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57,
            0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c,
            0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
        ];
        var Si = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b,
            0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95,
            0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72,
            0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9,
            0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8,
            0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11,
            0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2,
            0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe,
            0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88,
            0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a,
            0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17,
            0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
        ];
    
        // Transformations for encryption
        var T1 = [0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103,
            0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15,
            0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b,
            0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534,
            0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1,
            0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b,
            0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce,
            0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8,
            0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 0xbbd0d06b, 0xc5efef2a,
            0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0,
            0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504,
            0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335,
            0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7,
            0x3219192b, 0xe6737395, 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca,
            0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e,
            0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437,
            0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa,
            0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24,
            0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85,
            0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 0xc26161a3, 0x6a35355f, 0xae5757f9,
            0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970,
            0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 0x038c8c8f,
            0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11,
            0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a
        ];
        var T2 = [0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101,
            0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa,
            0xebb25959, 0xc98e4747, 0x0bfbf0f0, 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0,
            0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5,
            0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696,
            0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909,
            0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3,
            0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1,
            0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 0x6bbbd0d0, 0x2ac5efef,
            0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050,
            0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5,
            0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313,
            0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d,
            0x2b321919, 0x95e67373, 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646,
            0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a,
            0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4,
            0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656,
            0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c,
            0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a,
            0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 0xa3c26161, 0x5f6a3535, 0xf9ae5757,
            0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9,
            0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 0x8f038c8c,
            0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f,
            0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616
        ];
        var T3 = [0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201,
            0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa,
            0x59ebb259, 0x47c98e47, 0xf00bfbf0, 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0,
            0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5,
            0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796,
            0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209,
            0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3,
            0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1,
            0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 0xd06bbbd0, 0xef2ac5ef,
            0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050,
            0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5,
            0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613,
            0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d,
            0x192b3219, 0x7395e673, 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46,
            0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a,
            0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4,
            0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56,
            0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c,
            0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a,
            0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 0x61a3c261, 0x355f6a35, 0x57f9ae57,
            0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9,
            0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 0x8c8f038c,
            0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f,
            0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16
        ];
        var T4 = [0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302,
            0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef,
            0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b,
            0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1,
            0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137,
            0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12,
            0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d,
            0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879,
            0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 0xd0d06bbb, 0xefef2ac5,
            0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0,
            0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1,
            0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526,
            0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba,
            0x19192b32, 0x737395e6, 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c,
            0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14,
            0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3,
            0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac,
            0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438,
            0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f,
            0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 0x6161a3c2, 0x35355f6a, 0x5757f9ae,
            0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9,
            0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 0x8c8c8f03,
            0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e,
            0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c
        ];
    
        // Transformations for decryption
        var T5 = [0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6,
            0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502,
            0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844,
            0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360,
            0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2,
            0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b,
            0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75,
            0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f,
            0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 0xa17c0a47, 0x7c420fe9,
            0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964,
            0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16,
            0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb,
            0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510,
            0x13972240, 0x84c61120, 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c,
            0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36,
            0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e,
            0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4,
            0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af,
            0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f,
            0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 0x9d5eea04, 0x018c355d, 0xfa877473,
            0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935,
            0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 0xcaaff381,
            0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190,
            0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742
        ];
        var T6 = [0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d,
            0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75,
            0x12814cf0, 0xa38d4697, 0xc66bd3f9, 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8,
            0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133,
            0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02,
            0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c,
            0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb,
            0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4,
            0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 0x47a17c0a, 0xe97c420f,
            0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9,
            0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a,
            0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd,
            0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385,
            0x40139722, 0x2084c611, 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316,
            0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b,
            0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7,
            0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918,
            0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2,
            0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6,
            0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 0x049d5eea, 0x5d018c35, 0x73fa8774,
            0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9,
            0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 0x81caaff3,
            0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1,
            0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857
        ];
        var T7 = [0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76,
            0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f,
            0xf012814c, 0x97a38d46, 0xf9c66bd3, 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9,
            0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751,
            0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b,
            0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf,
            0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6,
            0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406,
            0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 0x0a47a17c, 0x0fe97c42,
            0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f,
            0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12,
            0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99,
            0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263,
            0x22401397, 0x112084c6, 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3,
            0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4,
            0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39,
            0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59,
            0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4,
            0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791,
            0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 0xea049d5e, 0x355d018c, 0x7473fa87,
            0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761,
            0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 0xf381caaf,
            0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456,
            0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8
        ];
        var T8 = [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad,
            0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3,
            0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e,
            0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097,
            0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272,
            0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a,
            0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4,
            0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04,
            0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c,
            0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a,
            0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c,
            0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee,
            0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042,
            0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b,
            0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698,
            0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e,
            0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e,
            0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31,
            0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17,
            0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa,
            0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7,
            0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca,
            0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064,
            0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0
        ];
    
        // Transformations for decryption key expansion
        var U1 = [0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553,
            0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c,
            0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9,
            0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935,
            0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec,
            0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6,
            0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3,
            0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c,
            0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86,
            0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9,
            0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c,
            0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1,
            0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88,
            0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f,
            0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691,
            0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee,
            0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f,
            0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d,
            0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68,
            0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff,
            0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d,
            0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca,
            0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f,
            0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3
        ];
        var U2 = [0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165,
            0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4,
            0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b,
            0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9,
            0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652,
            0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d,
            0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512,
            0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093,
            0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 0x8d764dd6, 0x867844db,
            0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a,
            0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225,
            0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0,
            0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b,
            0x9515929c, 0x9e1b9b91, 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462,
            0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76,
            0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927,
            0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4,
            0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83,
            0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc,
            0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 0xe97c420f, 0xe2724b02, 0xff605015,
            0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35,
            0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 0xcad731dc,
            0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3,
            0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697
        ];
        var U3 = [0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41,
            0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4,
            0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7,
            0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761,
            0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86,
            0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76,
            0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25,
            0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0,
            0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 0xd68d764d, 0xdb867844,
            0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21,
            0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2,
            0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe,
            0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789,
            0x9c951592, 0x919e1b9b, 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134,
            0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc,
            0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9,
            0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406,
            0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be,
            0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed,
            0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 0x0fe97c42, 0x02e2724b, 0x15ff6050,
            0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c,
            0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 0xdccad731,
            0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562,
            0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46
        ];
        var U4 = [0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e,
            0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8,
            0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba,
            0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7,
            0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d,
            0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad,
            0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf,
            0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69,
            0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 0x4dd68d76, 0x44db8678,
            0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e,
            0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc,
            0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d,
            0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807,
            0x929c9515, 0x9b919e1b, 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1,
            0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188,
            0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece,
            0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04,
            0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4,
            0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6,
            0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 0x420fe97c, 0x4b02e272, 0x5015ff60,
            0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01,
            0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 0x31dccad7,
            0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5,
            0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d
        ];
    
        function convertToInt32(bytes) {
            var result = [];
            for (var i = 0; i < bytes.length; i += 4) {
                result.push(
                    (bytes[i] << 24) |
                    (bytes[i + 1] << 16) |
                    (bytes[i + 2] << 8) |
                    bytes[i + 3]
                );
            }
            return result;
        }
    
        var AES = function (key) {
            if (!(this instanceof AES)) {
                throw Error('AES must be instanitated with `new`');
            }
    
            Object.defineProperty(this, 'key', {
                value: coerceArray(key, true)
            });
    
            this._prepare();
        }
    
        AES.prototype._prepare = function () {
    
            var rounds = numberOfRounds[this.key.length];
            if (rounds == null) {
                throw new Error('invalid key size (must be 16, 24 or 32 bytes)');
            }
    
            // encryption round keys
            this._Ke = [];
    
            // decryption round keys
            this._Kd = [];
    
            for (var i = 0; i <= rounds; i++) {
                this._Ke.push([0, 0, 0, 0]);
                this._Kd.push([0, 0, 0, 0]);
            }
    
            var roundKeyCount = (rounds + 1) * 4;
            var KC = this.key.length / 4;
    
            // convert the key into ints
            var tk = convertToInt32(this.key);
    
            // copy values into round key arrays
            var index;
            for (var i = 0; i < KC; i++) {
                index = i >> 2;
                this._Ke[index][i % 4] = tk[i];
                this._Kd[rounds - index][i % 4] = tk[i];
            }
    
            // key expansion (fips-197 section 5.2)
            var rconpointer = 0;
            var t = KC,
                tt;
            while (t < roundKeyCount) {
                tt = tk[KC - 1];
                tk[0] ^= ((S[(tt >> 16) & 0xFF] << 24) ^
                    (S[(tt >> 8) & 0xFF] << 16) ^
                    (S[tt & 0xFF] << 8) ^
                    S[(tt >> 24) & 0xFF] ^
                    (rcon[rconpointer] << 24));
                rconpointer += 1;
    
                // key expansion (for non-256 bit)
                if (KC != 8) {
                    for (var i = 1; i < KC; i++) {
                        tk[i] ^= tk[i - 1];
                    }
    
                    // key expansion for 256-bit keys is "slightly different" (fips-197)
                } else {
                    for (var i = 1; i < (KC / 2); i++) {
                        tk[i] ^= tk[i - 1];
                    }
                    tt = tk[(KC / 2) - 1];
    
                    tk[KC / 2] ^= (S[tt & 0xFF] ^
                        (S[(tt >> 8) & 0xFF] << 8) ^
                        (S[(tt >> 16) & 0xFF] << 16) ^
                        (S[(tt >> 24) & 0xFF] << 24));
    
                    for (var i = (KC / 2) + 1; i < KC; i++) {
                        tk[i] ^= tk[i - 1];
                    }
                }
    
                // copy values into round key arrays
                var i = 0,
                    r, c;
                while (i < KC && t < roundKeyCount) {
                    r = t >> 2;
                    c = t % 4;
                    this._Ke[r][c] = tk[i];
                    this._Kd[rounds - r][c] = tk[i++];
                    t++;
                }
            }
    
            // inverse-cipher-ify the decryption round key (fips-197 section 5.3)
            for (var r = 1; r < rounds; r++) {
                for (var c = 0; c < 4; c++) {
                    tt = this._Kd[r][c];
                    this._Kd[r][c] = (U1[(tt >> 24) & 0xFF] ^
                        U2[(tt >> 16) & 0xFF] ^
                        U3[(tt >> 8) & 0xFF] ^
                        U4[tt & 0xFF]);
                }
            }
        }
    
        AES.prototype.encrypt = function (plaintext) {
            if (plaintext.length != 16) {
                throw new Error('invalid plaintext size (must be 16 bytes)');
            }
    
            var rounds = this._Ke.length - 1;
            var a = [0, 0, 0, 0];
    
            // convert plaintext to (ints ^ key)
            var t = convertToInt32(plaintext);
            for (var i = 0; i < 4; i++) {
                t[i] ^= this._Ke[0][i];
            }
    
            // apply round transforms
            for (var r = 1; r < rounds; r++) {
                for (var i = 0; i < 4; i++) {
                    a[i] = (T1[(t[i] >> 24) & 0xff] ^
                        T2[(t[(i + 1) % 4] >> 16) & 0xff] ^
                        T3[(t[(i + 2) % 4] >> 8) & 0xff] ^
                        T4[t[(i + 3) % 4] & 0xff] ^
                        this._Ke[r][i]);
                }
                t = a.slice();
            }
    
            // the last round is special
            var result = createArray(16),
                tt;
            for (var i = 0; i < 4; i++) {
                tt = this._Ke[rounds][i];
                result[4 * i] = (S[(t[i] >> 24) & 0xff] ^ (tt >> 24)) & 0xff;
                result[4 * i + 1] = (S[(t[(i + 1) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff;
                result[4 * i + 2] = (S[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff;
                result[4 * i + 3] = (S[t[(i + 3) % 4] & 0xff] ^ tt) & 0xff;
            }
    
            return result;
        }
    
        AES.prototype.decrypt = function (ciphertext) {
            if (ciphertext.length != 16) {
                throw new Error('invalid ciphertext size (must be 16 bytes)');
            }
    
            var rounds = this._Kd.length - 1;
            var a = [0, 0, 0, 0];
    
            // convert plaintext to (ints ^ key)
            var t = convertToInt32(ciphertext);
            for (var i = 0; i < 4; i++) {
                t[i] ^= this._Kd[0][i];
            }
    
            // apply round transforms
            for (var r = 1; r < rounds; r++) {
                for (var i = 0; i < 4; i++) {
                    a[i] = (T5[(t[i] >> 24) & 0xff] ^
                        T6[(t[(i + 3) % 4] >> 16) & 0xff] ^
                        T7[(t[(i + 2) % 4] >> 8) & 0xff] ^
                        T8[t[(i + 1) % 4] & 0xff] ^
                        this._Kd[r][i]);
                }
                t = a.slice();
            }
    
            // the last round is special
            var result = createArray(16),
                tt;
            for (var i = 0; i < 4; i++) {
                tt = this._Kd[rounds][i];
                result[4 * i] = (Si[(t[i] >> 24) & 0xff] ^ (tt >> 24)) & 0xff;
                result[4 * i + 1] = (Si[(t[(i + 3) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff;
                result[4 * i + 2] = (Si[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff;
                result[4 * i + 3] = (Si[t[(i + 1) % 4] & 0xff] ^ tt) & 0xff;
            }
    
            return result;
        }
    
        /**
         *  Mode Of Operation - Electonic Codebook (ECB)
         */
        var ModeOfOperationECB = function (key) {
            if (!(this instanceof ModeOfOperationECB)) {
                throw Error('AES must be instanitated with `new`');
            }
    
            this.description = "Electronic Code Block";
            this.name = "ecb";
    
            this._aes = new AES(key);
        }
    
        ModeOfOperationECB.prototype.encrypt = function (plaintext) {
            plaintext = coerceArray(plaintext);
    
            if ((plaintext.length % 16) !== 0) {
                throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
            }
    
            var ciphertext = createArray(plaintext.length);
            var block = createArray(16);
    
            for (var i = 0; i < plaintext.length; i += 16) {
                copyArray(plaintext, block, 0, i, i + 16);
                block = this._aes.encrypt(block);
                copyArray(block, ciphertext, i);
            }
    
            return ciphertext;
        }
    
        ModeOfOperationECB.prototype.decrypt = function (ciphertext) {
            ciphertext = coerceArray(ciphertext);
    
            if ((ciphertext.length % 16) !== 0) {
                throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
            }
    
            var plaintext = createArray(ciphertext.length);
            var block = createArray(16);
    
            for (var i = 0; i < ciphertext.length; i += 16) {
                copyArray(ciphertext, block, 0, i, i + 16);
                block = this._aes.decrypt(block);
                copyArray(block, plaintext, i);
            }
    
            return plaintext;
        }
    
        /**
         *  Mode Of Operation - Cipher Block Chaining (CBC)
         */
        var ModeOfOperationCBC = function (key, iv) {
            if (!(this instanceof ModeOfOperationCBC)) {
                throw Error('AES must be instanitated with `new`');
            }
    
            this.description = "Cipher Block Chaining";
            this.name = "cbc";
    
            if (!iv) {
                iv = createArray(16);
    
            } else if (iv.length != 16) {
                throw new Error('invalid initialation vector size (must be 16 bytes)');
            }
    
            this._lastCipherblock = coerceArray(iv, true);
    
            this._aes = new AES(key);
        }
    
        ModeOfOperationCBC.prototype.encrypt = function (plaintext) {
            plaintext = coerceArray(plaintext);
    
            if ((plaintext.length % 16) !== 0) {
                throw new Error('invalid plaintext size (must be multiple of 16 bytes)');
            }
    
            var ciphertext = createArray(plaintext.length);
            var block = createArray(16);
    
            for (var i = 0; i < plaintext.length; i += 16) {
                copyArray(plaintext, block, 0, i, i + 16);
    
                for (var j = 0; j < 16; j++) {
                    block[j] ^= this._lastCipherblock[j];
                }
    
                this._lastCipherblock = this._aes.encrypt(block);
                copyArray(this._lastCipherblock, ciphertext, i);
            }
    
            return ciphertext;
        }
    
        ModeOfOperationCBC.prototype.decrypt = function (ciphertext) {
            ciphertext = coerceArray(ciphertext);
    
            if ((ciphertext.length % 16) !== 0) {
                throw new Error('invalid ciphertext size (must be multiple of 16 bytes)');
            }
    
            var plaintext = createArray(ciphertext.length);
            var block = createArray(16);
    
            for (var i = 0; i < ciphertext.length; i += 16) {
                copyArray(ciphertext, block, 0, i, i + 16);
                block = this._aes.decrypt(block);
    
                for (var j = 0; j < 16; j++) {
                    plaintext[i + j] = block[j] ^ this._lastCipherblock[j];
                }
    
                copyArray(ciphertext, this._lastCipherblock, 0, i, i + 16);
            }
    
            return plaintext;
        }
    
        /**
         *  Mode Of Operation - Cipher Feedback (CFB)
         */
        var ModeOfOperationCFB = function (key, iv, segmentSize) {
            if (!(this instanceof ModeOfOperationCFB)) {
                throw Error('AES must be instanitated with `new`');
            }
    
            this.description = "Cipher Feedback";
            this.name = "cfb";
    
            if (!iv) {
                iv = createArray(16);
    
            } else if (iv.length != 16) {
                throw new Error('invalid initialation vector size (must be 16 size)');
            }
    
            if (!segmentSize) {
                segmentSize = 1;
            }
    
            this.segmentSize = segmentSize;
    
            this._shiftRegister = coerceArray(iv, true);
    
            this._aes = new AES(key);
        }
    
        ModeOfOperationCFB.prototype.encrypt = function (plaintext) {
            if ((plaintext.length % this.segmentSize) != 0) {
                throw new Error('invalid plaintext size (must be segmentSize bytes)');
            }
    
            var encrypted = coerceArray(plaintext, true);
    
            var xorSegment;
            for (var i = 0; i < encrypted.length; i += this.segmentSize) {
                xorSegment = this._aes.encrypt(this._shiftRegister);
                for (var j = 0; j < this.segmentSize; j++) {
                    encrypted[i + j] ^= xorSegment[j];
                }
    
                // Shift the register
                copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
                copyArray(encrypted, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
            }
    
            return encrypted;
        }
    
        ModeOfOperationCFB.prototype.decrypt = function (ciphertext) {
            if ((ciphertext.length % this.segmentSize) != 0) {
                throw new Error('invalid ciphertext size (must be segmentSize bytes)');
            }
    
            var plaintext = coerceArray(ciphertext, true);
    
            var xorSegment;
            for (var i = 0; i < plaintext.length; i += this.segmentSize) {
                xorSegment = this._aes.encrypt(this._shiftRegister);
    
                for (var j = 0; j < this.segmentSize; j++) {
                    plaintext[i + j] ^= xorSegment[j];
                }
    
                // Shift the register
                copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize);
                copyArray(ciphertext, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize);
            }
    
            return plaintext;
        }
    
        /**
         *  Mode Of Operation - Output Feedback (OFB)
         */
        var ModeOfOperationOFB = function (key, iv) {
            if (!(this instanceof ModeOfOperationOFB)) {
                throw Error('AES must be instanitated with `new`');
            }
    
            this.description = "Output Feedback";
            this.name = "ofb";
    
            if (!iv) {
                iv = createArray(16);
    
            } else if (iv.length != 16) {
                throw new Error('invalid initialation vector size (must be 16 bytes)');
            }
    
            this._lastPrecipher = coerceArray(iv, true);
            this._lastPrecipherIndex = 16;
    
            this._aes = new AES(key);
        }
    
        ModeOfOperationOFB.prototype.encrypt = function (plaintext) {
            var encrypted = coerceArray(plaintext, true);
    
            for (var i = 0; i < encrypted.length; i++) {
                if (this._lastPrecipherIndex === 16) {
                    this._lastPrecipher = this._aes.encrypt(this._lastPrecipher);
                    this._lastPrecipherIndex = 0;
                }
                encrypted[i] ^= this._lastPrecipher[this._lastPrecipherIndex++];
            }
    
            return encrypted;
        }
    
        // Decryption is symetric
        ModeOfOperationOFB.prototype.decrypt = ModeOfOperationOFB.prototype.encrypt;
    
        /**
         *  Counter object for CTR common mode of operation
         */
        var Counter = function (initialValue) {
            if (!(this instanceof Counter)) {
                throw Error('Counter must be instanitated with `new`');
            }
    
            // We allow 0, but anything false-ish uses the default 1
            if (initialValue !== 0 && !initialValue) {
                initialValue = 1;
            }
    
            if (typeof (initialValue) === 'number') {
                this._counter = createArray(16);
                this.setValue(initialValue);
    
            } else {
                this.setBytes(initialValue);
            }
        }
    
        Counter.prototype.setValue = function (value) {
            if (typeof (value) !== 'number' || parseInt(value) != value) {
                throw new Error('invalid counter value (must be an integer)');
            }
    
            for (var index = 15; index >= 0; --index) {
                this._counter[index] = value % 256;
                value = value >> 8;
            }
        }
    
        Counter.prototype.setBytes = function (bytes) {
            bytes = coerceArray(bytes, true);
    
            if (bytes.length != 16) {
                throw new Error('invalid counter bytes size (must be 16 bytes)');
            }
    
            this._counter = bytes;
        };
    
        Counter.prototype.increment = function () {
            for (var i = 15; i >= 0; i--) {
                if (this._counter[i] === 255) {
                    this._counter[i] = 0;
                } else {
                    this._counter[i]++;
                    break;
                }
            }
        }
    
        /**
         *  Mode Of Operation - Counter (CTR)
         */
        var ModeOfOperationCTR = function (key, counter) {
            if (!(this instanceof ModeOfOperationCTR)) {
                throw Error('AES must be instanitated with `new`');
            }
    
            this.description = "Counter";
            this.name = "ctr";
    
            if (!(counter instanceof Counter)) {
                counter = new Counter(counter)
            }
    
            this._counter = counter;
    
            this._remainingCounter = null;
            this._remainingCounterIndex = 16;
    
            this._aes = new AES(key);
        }
    
        ModeOfOperationCTR.prototype.encrypt = function (plaintext) {
            var encrypted = coerceArray(plaintext, true);
    
            for (var i = 0; i < encrypted.length; i++) {
                if (this._remainingCounterIndex === 16) {
                    this._remainingCounter = this._aes.encrypt(this._counter._counter);
                    this._remainingCounterIndex = 0;
                    this._counter.increment();
                }
                encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++];
            }
    
            return encrypted;
        }
    
        // Decryption is symetric
        ModeOfOperationCTR.prototype.decrypt = ModeOfOperationCTR.prototype.encrypt;
    
        ///////////////////////
        // Padding
    
        // See:https://tools.ietf.org/html/rfc2315
        function pkcs7pad(data) {
            data = coerceArray(data, true);
            var padder = 16 - (data.length % 16);
            var result = createArray(data.length + padder);
            copyArray(data, result);
            for (var i = data.length; i < result.length; i++) {
                result[i] = padder;
            }
            return result;
        }
    
        function pkcs7strip(data) {
            data = coerceArray(data, true);
            if (data.length < 16) {
                throw new Error('PKCS#7 invalid length');
            }
    
            var padder = data[data.length - 1];
            if (padder > 16) {
                throw new Error('PKCS#7 padding byte out of range');
            }
    
            var length = data.length - padder;
            for (var i = 0; i < padder; i++) {
                if (data[length + i] !== padder) {
                    throw new Error('PKCS#7 invalid padding byte');
                }
            }
    
            var result = createArray(length);
            copyArray(data, result, 0, 0, length);
            return result;
        }
    
        ///////////////////////
        // Exporting
    
        // The block cipher
        var aesjs = {
            AES: AES,
            Counter: Counter,
    
            ModeOfOperation: {
                ecb: ModeOfOperationECB,
                cbc: ModeOfOperationCBC,
                cfb: ModeOfOperationCFB,
                ofb: ModeOfOperationOFB,
                ctr: ModeOfOperationCTR
            },
    
            utils: {
                hex: convertHex,
                utf8: convertUtf8
            },
    
            padding: {
                pkcs7: {
                    pad: pkcs7pad,
                    strip: pkcs7strip
                }
            },
    
            _arrayTest: {
                coerceArray: coerceArray,
                createArray: createArray,
                copyArray: copyArray,
            }
        };
    
        // node.js
        if (typeof exports !== 'undefined') {
            module.exports = aesjs
    
            // RequireJS/AMD
            // http://www.requirejs.org/docs/api.html
            // https://github.com/amdjs/amdjs-api/wiki/AMD
        } else if (typeof (define) === 'function' && define.amd) {
            define(aesjs);
    
            // Web Browsers
        } else {
    
            // If there was an existing library at "aesjs" make sure it's still available
            if (root.aesjs) {
                aesjs._aesjs = root.aesjs;
            }
    
            root.aesjs = aesjs;
        }
    
    })(this);

    View.xml

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
        xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Encrypting and Decrypting Data in SAP UI5 using aes.js">
                        <content>
                            <VBox>
                                <Label text="Password"/>
                                <Input id="idPassword" value=""/>
                                <Button icon="sap-icon://locked" text="Encrypt" press="onEncrypt"/>
                                <Text text="" id="idEncrypted"/>
                                <Button visible="false" id="idDecryptButton" icon="sap-icon://unlocked" text="Decrypt" press="onDecrypt"/>
                                <Text text="" id="idDecrypted"/>
                            </VBox>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

    Controller.js

    sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "sap/m/MessageBox",
        "sap/m/MessageToast",
        "sap/ui/model/json/JSONModel",
        "Test/Test/js/aesjs"
    
    ], function (Controller, MessageBox, MessageToast, JSONModel) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            /**
             * getEncryptedKey is invoked from a function. 
             * Input: string key value
             * Output: encrypted key value
             */
    
            getEncryptedKey: function (sKey) {
                // An example 128-bit key (16 bytes * 8 bits/byte = 128 bits)
                var key = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
                // Convert text to bytes
                var text = sKey;
                var textBytes = aesjs.utils.utf8.toBytes(text);
    
                // The counter is optional, and if omitted will begin at 1
                var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
                var encryptedBytes = aesCtr.encrypt(textBytes);
    
                // To print or store the binary data, you may convert it to hex
                var encryptedHex = aesjs.utils.hex.fromBytes(encryptedBytes);
                return encryptedHex;
            },
    
            /**
             * getDecryptedKey is invoked from a function. 
             * Input: string key value
             * Output: Decrypted key value
             */
    
            getDecryptedKey: function (sEncryptedHex) {
                // An example 128-bit key (16 bytes * 8 bits/byte = 128 bits)
                var key = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
                // When ready to decrypt the hex string, convert it back to bytes
                var encryptedBytes = aesjs.utils.hex.toBytes(sEncryptedHex);
    
                // The counter mode of operation maintains internal state, so to
                // decrypt a new instance must be instantiated.
                var aesCtr = new aesjs.ModeOfOperation.ctr(key, new aesjs.Counter(5));
                var decryptedBytes = aesCtr.decrypt(encryptedBytes);
    
                // Convert our bytes back into text
                var decryptedText = aesjs.utils.utf8.fromBytes(decryptedBytes);
                return decryptedText;
            },
    
            onEncrypt: function (oEvent) {
                // Fetching input
                var input = this.byId("idPassword").getValue();
                //Encrypting Data
                var output = this.getEncryptedKey(input);
                //showing output
                this.byId("idEncrypted").setText(output);
                //set decrypt button visible
                this.byId("idDecryptButton").setVisible(true);
            },
    
            onDecrypt: function (oEvent) {
                // Fetching input
                var input = this.byId("idEncrypted").getText();
                //Encrypting Data
                var output = this.getDecryptedKey(input);
                //showing output
                this.byId("idDecrypted").setText(output);
            }
    
        });
    });

    Output

    Output Encrypting and Decrypting Data in SAP UI5 using aes

  • Scan QR Code Integration in SAP UI5

    Introduction

    In SAP’s world, the UI5 and Fiori Apps are used extensively to perform a large number of operations. Among these operations, there is a common requirement of a warehouse to scan a QR Code pasted over a material and get the material number from it. It is similar to the QR Code scanning you might have seen at a shopping mall outlet. In this article, we will learn simple steps for Scan QR Code Integration in SAP UI5

    Pre requisite of QR Code Scanning in SAP UI5 via Mobile

    The QR Code scanning works fine on a laptop, but to make it work on a mobile phone or a tablet, you need to deploy your UI5 application as a Fiori Application. The fiori application should be used via the Fiori Launchpad mobile application. You can download the same from here:

    SAP Mobile Start: Fiori Launchpad for Android

    SAP Mobile Start: Fiori Launchpad for iOS

    Steps to create an SAP UI5 to scan a QR Code

    Steps to Integrate QR Code Scan

    To create a scanning app, follow the steps below:

    1. Create a UI5 project in any IDE

    2. Create a view and add a button to start scanning, and an input box to get the scanned data. The code would be like mentioned below:

    <mvc:View controllerName="Test.Test.controller.Main" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m" xmlns:core="sap.ui.core"
        xmlns:html="http://www.w3.org/1999/xhtml">
        <Shell id="shell">
            <App id="app">
                <pages>
                    <Page id="page" title="Scan QR Code Integration in SAP UI5">
                        <content>
                            <VBox>
                                <Button icon="sap-icon://qr-code" text="Scan" press="onScan"/>
                                <Label text="Material"/>
                                <Input id="materialNumber" value=""/>
                            </VBox>
                        </content>
                    </Page>
                </pages>
            </App>
        </Shell>
    </mvc:View>

    Step 03: Add BarcodeScanner namespace and use it to scan the bar code, as shown below:

    sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "sap/m/MessageBox",
        "sap/m/MessageToast",
        "sap/ui/model/json/JSONModel",
        "sap/ndc/BarcodeScanner",
    ], function (Controller, MessageBox, MessageToast, JSONModel, BarcodeScanner) {
        "use strict";
    
        return Controller.extend("Test.Test.controller.Main", {
            onScan: function (oEvent) {
                var that = this;
                BarcodeScanner.scan(
                    function (mResult) {
                        if (!mResult.cancelled) {
                            that.getView().byId("materialNumber").setValue(mResult.text);
                            MessageBox.show("We got a QR code\n" +
                                "Result: " + mResult.text + "\n" +
                                "Format: " + mResult.format + "\n");
                        }
                    },
                    function (Error) {
                        alert("Scanning failed: " + Error);
                    }
                );
            },
    
        });
    });

    Note: If your scanning is not getting started, turn on the given extension in WebIDE:

    Hybrid App Toolkit

    Output

    Before Scanning

    Scan QR Code Integration in SAP UI5 before scan

    During Scanning

    Scan QR Code Integration in SAP UI5 during scan

    After Scanning

    Scan QR Code Integration in SAP UI5 after scan