This commit is contained in:
2024-08-29 19:05:53 +05:30
commit 6073a08a6d
24 changed files with 1436 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

6
.htaccess Normal file
View File

@@ -0,0 +1,6 @@
RewriteEngine On
RewriteCond $1 !^(index\.php)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?/$1 [L]

BIN
assets/.DS_Store vendored Normal file

Binary file not shown.

48
assets/css/footer.css Normal file
View File

@@ -0,0 +1,48 @@
footer {
background-color: #F8F8FD;
padding: 33px 20px; /* Increased padding for a larger footer */
border: none;
width: 100%;
box-sizing: border-box;
}
.footer-container {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 1120px;
font-size: 12px; /* Slightly increased font size */
margin: 0 auto;
width: 100%;
box-sizing: border-box;
flex-wrap: wrap;
}
.footer-container p {
margin: 0;
padding-bottom: 20px; /* Increased padding for spacing */
}
.footer-links {
margin-top: 15px; /* Increased margin for better spacing */
}
.footer-links a {
margin: 0 12px; /* Slightly increased margin between links */
text-decoration: none;
color: #A2ABB8;
font-weight: 550;
font-size: 10px;
}
.footer-links a:hover {
text-decoration: underline;
}
.footer-img {
width: 20px;
margin: 0;
position: relative;
top: 2px;
left: -5px;
}

55
assets/css/header.css Normal file
View File

@@ -0,0 +1,55 @@
/* header.css */
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background-color: #ffffff;
border-bottom: 1px solid #F2F2F2;
position: fixed;
top: 0;
width: 97%;
z-index: 1000;
}
.logo {
display: flex;
align-items: center;
font-weight: 500;
font-size: 18px;
}
.logo-img {
width: 35px;
margin-right: 10px; /* Spacing between logo and text */
}
nav ul {
list-style: none;
display: flex;
gap: 40px;
margin: 0;
}
nav ul li a {
text-decoration: none;
color: #697483; /* Default color for inactive links */
font-size: 14px;
font-weight: 500;
transition: color 0.3s; /* Smooth color transition */
}
nav ul li a.active {
color: #BEC7D5; /* Color for active link */
}
nav ul li a:not(.disabled):hover {
color: #272B2F; /* Color on hover for non-disabled links */
}
nav ul li a.disabled {
color: #BEC7D5; /* Color for disabled link */
pointer-events: none; /* Disable click events */
cursor: default; /* Change cursor to default */
}

203
assets/css/home.css Normal file
View File

@@ -0,0 +1,203 @@
body {
font-family: "Montserrat", sans-serif;
margin: 0;
padding: 0;
background-color: #ffffff;
color: #333333;
}
main {
padding: 60px 20px;
text-align: center;
}
.shorten-section h1 {
color: #171C24;
margin-top: 65px;
font-size: 45px;
font-weight: 700;
margin-bottom: 0px;
}
.shorten-section h2 {
color: #677583;
margin-top: 0px;
font-size: 45px;
font-weight: 700;
margin-bottom: 45px;
}
.shorten-section p {
color:#3C4B62;
margin-top: -15px;
margin-bottom: 45px;
font-size: 18px;
line-height: 35px;
}
.shorten-form {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
margin-bottom: 80px;
position: relative;
}
.shorten-form input {
font-family: "Montserrat", sans-serif;
padding: 18px 45px; /* Adjust padding to make space for the icon */
width: 450px;
border: none; /* Remove border */
border-radius: 5px; /* Rounded corners */
font-size: 16px;
background-color: #ffffff;
color: #333333;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.082); /* Soft shadow */
outline: none;
box-sizing: border-box;
transition: box-shadow 0.3s ease;
}
.shorten-form input::placeholder {
color: #BEC7D5; /* Light gray placeholder text */
font-weight: 500;
}
.shorten-form input:focus {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.150); /* Slightly stronger shadow on focus */
}
.shorten-form input:hover {
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.150); /* Slight shadow change on hover */
}
.shorten-form .search-icon {
position: absolute;
left: 16px; /* Position the icon inside the input */
font-size: 20px;
color: #BEC7D5;
}
.shorten-form button {
font-family: "Montserrat", sans-serif;
padding: 18px 45px;
background-color: #4d555cec;
color: #ffffff;
border: none;
border-radius: 5px; /* Same rounded corners as the input */
cursor: pointer;
font-weight: 600;
font-size: 16px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.082); /* Same shadow as the input */
outline: none;
box-sizing: border-box;
transition: box-shadow 0.3s ease, background-color 0.3s ease;
}
.shorten-form button:hover,
.shorten-form button.typing-active {
background-color: #171C24;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.250); /* Slight shadow change on hover */
}
.shorten-form button:focus {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.250); /* Slightly stronger shadow on focus */
}
.shortened-links h2 {
font-size: 18px;
margin-right: 500px;
margin-bottom: 25px;
font-weight: 550;
color: #A2ABB8;
}
.custom-link {
color: #387FFF;
text-decoration: none;
position: relative;
}
.custom-link::after {
content: "";
display: block;
height: 1px;
background-color: #387FFF;
position: absolute;
bottom: -2px; /* Adjust this value to position the underline */
left: 0;
right: 0;
transform: scaleX(0);
transition: transform 0.3s;
}
.custom-link:hover::after {
transform: scaleX(1);
}
#links-list {
list-style: none;
padding: 0;
max-width: 700px;
margin: 0 auto;
font-size: 16px;
}
#links-list li {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background-color: #ffffff;
border: 1px solid #dddddd;
border-radius: 8px;
margin-bottom: 15px;
}
.link-icon {
margin-right: -20px;
}
.link-info {
display: flex;
flex-direction: column;
flex-grow: 1;
max-width: 500px;
}
.short-link {
font-weight: 550;
margin-bottom: 3px;
color:#171C24 ;
white-space: nowrap;
text-overflow: ellipsis;
margin-right: 380px;
font-size: 16px;
}
.long-link {
color: #677583;
overflow: hidden;
margin-bottom: 0px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
text-align: left;
}
.copy-btn,
.delete-btn {
background: none;
border: none;
cursor: pointer;
width: 24px;
height: 24px;
padding: 0;
}
.copy-btn img,
.delete-btn img {
width: 100%;
height: 100%;
}

BIN
assets/images/.DS_Store vendored Normal file

Binary file not shown.

BIN
assets/images/copy.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

BIN
assets/images/delete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

BIN
assets/images/url.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

34
assets/images/url.svg Normal file
View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="128px" height="86px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
<g><path style="opacity:0.996" fill="#84819E" d="M 74.5,5.5 C 75.6216,4.84417 76.9549,4.51084 78.5,4.5C 80.8825,4.36103 82.8825,5.02769 84.5,6.5C 81.1667,6.16667 77.8333,5.83333 74.5,5.5 Z"/></g>
<g><path style="opacity:0.992" fill="#84819E" d="M 67.5,5.5 C 67.8333,5.5 68.1667,5.5 68.5,5.5C 70.5,5.5 72.5,5.5 74.5,5.5C 72.2854,6.2679 69.9521,6.93457 67.5,7.5C 67.5,6.83333 67.5,6.16667 67.5,5.5 Z"/></g>
<g><path style="opacity:0.994" fill="#84819E" d="M 74.5,5.5 C 77.8333,5.83333 81.1667,6.16667 84.5,6.5C 85.1667,6.5 85.8333,6.5 86.5,6.5C 87.5622,9.37805 89.5622,11.378 92.5,12.5C 92.8417,13.3382 93.5084,13.6716 94.5,13.5C 95.0916,16.1272 95.4249,18.7938 95.5,21.5C 95.6655,25.5138 95.4988,29.5138 95,33.5C 93.5187,34.4709 92.6854,35.8042 92.5,37.5C 88.7753,40.8876 85.4419,44.5542 82.5,48.5C 79.3497,50.577 76.0164,52.4104 72.5,54C 67.8065,54.5639 63.1398,54.3973 58.5,53.5C 53.6788,51.567 51.0121,47.9003 50.5,42.5C 54.5357,42.3533 57.8691,43.8533 60.5,47C 62.0249,48.0086 63.6916,48.5086 65.5,48.5C 68.0593,48.8016 70.3926,48.4682 72.5,47.5C 74.3797,47.7709 75.713,47.1042 76.5,45.5C 78.5,42.8333 80.8333,40.5 83.5,38.5C 84.4959,38.5858 85.3292,38.2524 86,37.5C 87.4213,35.5952 88.588,33.5952 89.5,31.5C 90.1174,31.3893 90.6174,31.056 91,30.5C 91.6667,27.1667 91.6667,23.8333 91,20.5C 90.6174,19.944 90.1174,19.6107 89.5,19.5C 88.9078,15.9111 86.9078,13.5778 83.5,12.5C 83.1667,12.5 82.8333,12.5 82.5,12.5C 81.6661,11.2521 80.3328,10.5854 78.5,10.5C 76.9549,10.5108 75.6216,10.8442 74.5,11.5C 74.5,12.1667 74.1667,12.5 73.5,12.5C 69.1534,13.4663 65.4868,15.7996 62.5,19.5C 60.9291,20.3094 59.2624,20.6427 57.5,20.5C 57.0225,16.3104 58.6892,13.3104 62.5,11.5C 64.889,11.0212 66.5557,9.6879 67.5,7.5C 69.9521,6.93457 72.2854,6.2679 74.5,5.5 Z"/></g>
<g><path style="opacity:0.929" fill="#84819E" d="M 93.5,39.5 C 93.5,38.8333 93.5,38.1667 93.5,37.5C 97.0823,32.5919 98.0823,27.2585 96.5,21.5C 96.8893,18.4467 96.2227,15.78 94.5,13.5C 93.5084,13.6716 92.8417,13.3382 92.5,12.5C 91.0499,10.0772 89.0499,8.07725 86.5,6.5C 85.8333,6.5 85.1667,6.5 84.5,6.5C 82.8825,5.02769 80.8825,4.36103 78.5,4.5C 76.9549,4.51084 75.6216,4.84417 74.5,5.5C 72.5,5.5 70.5,5.5 68.5,5.5C 83.1693,-0.0869892 93.336,4.57968 99,19.5C 100.477,27.2156 98.644,33.8822 93.5,39.5 Z"/></g>
<g><path style="opacity:0.937" fill="#84819E" d="M 67.5,5.5 C 67.5,6.16667 67.5,6.83333 67.5,7.5C 65.2054,8.13554 63.5387,9.46888 62.5,11.5C 58.6892,13.3104 57.0225,16.3104 57.5,20.5C 58.9187,21.4511 60.5853,21.7845 62.5,21.5C 62.1344,22.6946 61.301,23.3613 60,23.5C 55.394,22.6893 53.7273,20.0227 55,15.5C 58.4839,11.1689 62.6505,7.83561 67.5,5.5 Z"/></g>
<g><path style="opacity:0.969" fill="#84819E" d="M 67.5,7.5 C 66.5557,9.6879 64.889,11.0212 62.5,11.5C 63.5387,9.46888 65.2054,8.13554 67.5,7.5 Z"/></g>
<g><path style="opacity:0.043" fill="#84819E" d="M 74.5,11.5 C 75.6216,10.8442 76.9549,10.5108 78.5,10.5C 80.3328,10.5854 81.6661,11.2521 82.5,12.5C 79.8728,11.9084 77.2062,11.5751 74.5,11.5 Z"/></g>
<g><path style="opacity:1" fill="#84819E" d="M 86.5,6.5 C 89.0499,8.07725 91.0499,10.0772 92.5,12.5C 89.5622,11.378 87.5622,9.37805 86.5,6.5 Z"/></g>
<g><path style="opacity:0.667" fill="#84819E" d="M 83.5,12.5 C 86.9078,13.5778 88.9078,15.9111 89.5,19.5C 88.8333,19.1667 88.1667,18.8333 87.5,18.5C 86.5589,16.2279 85.2255,14.2279 83.5,12.5 Z"/></g>
<g><path style="opacity:0.42" fill="#84819E" d="M 73.5,12.5 C 69.59,15.0644 65.9233,18.0644 62.5,21.5C 60.5853,21.7845 58.9187,21.4511 57.5,20.5C 59.2624,20.6427 60.9291,20.3094 62.5,19.5C 65.4868,15.7996 69.1534,13.4663 73.5,12.5 Z"/></g>
<g><path style="opacity:1" fill="#84819E" d="M 94.5,13.5 C 96.2227,15.78 96.8893,18.4467 96.5,21.5C 96.1667,21.5 95.8333,21.5 95.5,21.5C 95.4249,18.7938 95.0916,16.1272 94.5,13.5 Z"/></g>
<g><path style="opacity:0.997" fill="#84819E" d="M 89.5,19.5 C 90.1174,19.6107 90.6174,19.944 91,20.5C 91.6667,23.8333 91.6667,27.1667 91,30.5C 90.6174,31.056 90.1174,31.3893 89.5,31.5C 90.8333,27.5 90.8333,23.5 89.5,19.5 Z"/></g>
<g><path style="opacity:0.997" fill="#84819E" d="M 95.5,21.5 C 95.8333,21.5 96.1667,21.5 96.5,21.5C 98.0823,27.2585 97.0823,32.5919 93.5,37.5C 93.1667,37.5 92.8333,37.5 92.5,37.5C 92.6854,35.8042 93.5187,34.4709 95,33.5C 95.4988,29.5138 95.6655,25.5138 95.5,21.5 Z"/></g>
<g><path style="opacity:0.994" fill="#84819E" d="M 49.5,28.5 C 55.473,27.7419 60.8063,29.0752 65.5,32.5C 66.5,34.8333 68.1667,36.5 70.5,37.5C 69.4766,41.3999 67.1433,42.3999 63.5,40.5C 59.7311,35.1146 54.7311,33.4479 48.5,35.5C 46.9557,35.7031 45.6223,36.3698 44.5,37.5C 41.1581,40.8761 37.8248,44.2094 34.5,47.5C 33.0476,48.9397 32.0476,50.6064 31.5,52.5C 31.5,52.8333 31.5,53.1667 31.5,53.5C 30.2353,54.5145 29.5687,56.0145 29.5,58C 29.5085,59.7067 29.8418,61.2067 30.5,62.5C 31.3127,64.2608 32.3127,65.9275 33.5,67.5C 34.0241,70.1878 35.6908,71.6878 38.5,72C 41.6965,72.8045 44.6965,72.6378 47.5,71.5C 50.8573,71.7841 53.1906,70.4507 54.5,67.5C 56.4532,64.0219 59.4532,62.3552 63.5,62.5C 63.6602,64.1992 63.4935,65.8659 63,67.5C 59.7515,71.4189 55.9181,74.5856 51.5,77C 48.5318,77.6936 45.5318,78.1936 42.5,78.5C 38.0002,78.2294 34.0002,76.8961 30.5,74.5C 29.2013,71.6047 27.5346,68.938 25.5,66.5C 24.5033,60.458 24.8366,54.458 26.5,48.5C 31.0755,42.2537 36.4088,36.587 42.5,31.5C 45.3852,31.357 47.7185,30.357 49.5,28.5 Z"/></g>
<g><path style="opacity:0.961" fill="#84819E" d="M 87.5,18.5 C 88.1667,18.8333 88.8333,19.1667 89.5,19.5C 90.8333,23.5 90.8333,27.5 89.5,31.5C 86.7997,33.2344 84.7997,35.5677 83.5,38.5C 80.8333,40.5 78.5,42.8333 76.5,45.5C 74.847,45.6596 73.5137,46.3263 72.5,47.5C 70.3926,48.4682 68.0593,48.8016 65.5,48.5C 65.5,47.8333 65.5,47.1667 65.5,46.5C 68.3198,46.7525 70.9865,46.2525 73.5,45C 78,40.5 82.5,36 87,31.5C 88.8249,27.2379 88.9916,22.9046 87.5,18.5 Z"/></g>
<g><path style="opacity:0.929" fill="#84819E" d="M 63.5,40.5 C 67.1433,42.3999 69.4766,41.3999 70.5,37.5C 69.8333,34.8333 68.1667,33.1667 65.5,32.5C 60.8063,29.0752 55.473,27.7419 49.5,28.5C 46.7282,28.7587 44.3949,29.7587 42.5,31.5C 36.4088,36.587 31.0755,42.2537 26.5,48.5C 25.8826,48.6107 25.3826,48.944 25,49.5C 22.8661,55.3714 23.0328,61.0381 25.5,66.5C 27.5346,68.938 29.2013,71.6047 30.5,74.5C 26.8467,73.0106 24.3467,70.3439 23,66.5C 20.3485,58.6647 21.3485,51.3314 26,44.5C 31.9512,37.5423 38.7845,31.7089 46.5,27C 55.9478,24.7412 64.1145,26.9078 71,33.5C 72.5666,36.3945 72.7333,39.3945 71.5,42.5C 69.1432,42.6633 66.8098,42.4966 64.5,42C 63.944,41.6174 63.6107,41.1174 63.5,40.5 Z"/></g>
<g><path style="opacity:1" fill="#84819E" d="M 49.5,28.5 C 47.7185,30.357 45.3852,31.357 42.5,31.5C 44.3949,29.7587 46.7282,28.7587 49.5,28.5 Z"/></g>
<g><path style="opacity:1" fill="#84819E" d="M 65.5,32.5 C 68.1667,33.1667 69.8333,34.8333 70.5,37.5C 68.1667,36.5 66.5,34.8333 65.5,32.5 Z"/></g>
<g><path style="opacity:0.992" fill="#84819E" d="M 89.5,31.5 C 88.588,33.5952 87.4213,35.5952 86,37.5C 85.3292,38.2524 84.4959,38.5858 83.5,38.5C 84.7997,35.5677 86.7997,33.2344 89.5,31.5 Z"/></g>
<g><path style="opacity:0.745" fill="#84819E" d="M 48.5,35.5 C 43.4721,40.8595 38.4721,46.1929 33.5,51.5C 32.8333,51.8333 32.1667,52.1667 31.5,52.5C 32.0476,50.6064 33.0476,48.9397 34.5,47.5C 37.8248,44.2094 41.1581,40.8761 44.5,37.5C 45.6223,36.3698 46.9557,35.7031 48.5,35.5 Z"/></g>
<g><path style="opacity:0.071" fill="#84819E" d="M 92.5,37.5 C 92.8333,37.5 93.1667,37.5 93.5,37.5C 93.5,38.1667 93.5,38.8333 93.5,39.5C 90.1053,43.8976 86.1053,47.5643 81.5,50.5C 81.8333,49.8333 82.1667,49.1667 82.5,48.5C 85.4419,44.5542 88.7753,40.8876 92.5,37.5 Z"/></g>
<g><path style="opacity:1" fill="#84819E" d="M 76.5,45.5 C 75.713,47.1042 74.3797,47.7709 72.5,47.5C 73.5137,46.3263 74.847,45.6596 76.5,45.5 Z"/></g>
<g><path style="opacity:0.537" fill="#84819E" d="M 65.5,46.5 C 65.5,47.1667 65.5,47.8333 65.5,48.5C 63.6916,48.5086 62.0249,48.0086 60.5,47C 57.8691,43.8533 54.5357,42.3533 50.5,42.5C 51.0121,47.9003 53.6788,51.567 58.5,53.5C 51.32,52.3441 48.6533,48.3441 50.5,41.5C 54.6423,40.0602 57.9756,41.2268 60.5,45C 62.0249,46.0086 63.6916,46.5086 65.5,46.5 Z"/></g>
<g><path style="opacity:1" fill="#84819E" d="M 26.5,48.5 C 24.8366,54.458 24.5033,60.458 25.5,66.5C 23.0328,61.0381 22.8661,55.3714 25,49.5C 25.3826,48.944 25.8826,48.6107 26.5,48.5 Z"/></g>
<g><path style="opacity:0.051" fill="#84819E" d="M 82.5,48.5 C 82.1667,49.1667 81.8333,49.8333 81.5,50.5C 80.2287,52.9339 78.2287,54.4339 75.5,55C 70.5,55.6667 65.5,55.6667 60.5,55C 59.5842,54.7216 58.9175,54.2216 58.5,53.5C 63.1398,54.3973 67.8065,54.5639 72.5,54C 76.0164,52.4104 79.3497,50.577 82.5,48.5 Z"/></g>
<g><path style="opacity:0.996" fill="#84819E" d="M 31.5,53.5 C 30.8413,56.4552 30.5079,59.4552 30.5,62.5C 30.5079,59.4552 30.8413,56.4552 31.5,53.5 Z"/></g>
<g><path style="opacity:0.647" fill="#84819E" d="M 33.5,51.5 C 31.5399,57.5757 32.5399,63.0757 36.5,68C 40.3749,69.5204 44.3749,69.8538 48.5,69C 52.3819,65.6106 56.3819,62.4439 60.5,59.5C 66.0221,59.6078 67.8554,62.2744 66,67.5C 65.6174,68.056 65.1174,68.3893 64.5,68.5C 64.7947,66.2646 64.4614,64.2646 63.5,62.5C 59.4532,62.3552 56.4532,64.0219 54.5,67.5C 52.1246,68.9017 49.7912,70.235 47.5,71.5C 42.2489,71.7923 37.5822,70.4589 33.5,67.5C 32.3127,65.9275 31.3127,64.2608 30.5,62.5C 30.5079,59.4552 30.8413,56.4552 31.5,53.5C 31.5,53.1667 31.5,52.8333 31.5,52.5C 32.1667,52.1667 32.8333,51.8333 33.5,51.5 Z"/></g>
<g><path style="opacity:0.984" fill="#84819E" d="M 54.5,67.5 C 53.1906,70.4507 50.8573,71.7841 47.5,71.5C 49.7912,70.235 52.1246,68.9017 54.5,67.5 Z"/></g>
<g><path style="opacity:1" fill="#84819E" d="M 33.5,67.5 C 37.5822,70.4589 42.2489,71.7923 47.5,71.5C 44.6965,72.6378 41.6965,72.8045 38.5,72C 35.6908,71.6878 34.0241,70.1878 33.5,67.5 Z"/></g>
<g><path style="opacity:0.949" fill="#84819E" d="M 63.5,62.5 C 64.4614,64.2646 64.7947,66.2646 64.5,68.5C 57.2987,78.7658 47.6321,82.2658 35.5,79C 33.3395,78.0041 31.6728,76.5041 30.5,74.5C 34.0002,76.8961 38.0002,78.2294 42.5,78.5C 45.5318,78.1936 48.5318,77.6936 51.5,77C 55.9181,74.5856 59.7515,71.4189 63,67.5C 63.4935,65.8659 63.6602,64.1992 63.5,62.5 Z"/></g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

0
assets/js/header.js Normal file
View File

69
assets/js/home.js Normal file
View File

@@ -0,0 +1,69 @@
const form = document.querySelector(".shorten-form"),
urlInput = document.querySelector("#url-input"),
shortenBtn = document.querySelector("#shorten-btn"),
linksList = document.querySelector("#links-list");
shortenBtn.onclick = () => {
let xhr = new XMLHttpRequest();
xhr.open("POST", "php/url-controll.php", true);
xhr.onload = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
let data = xhr.response;
if (data.length <= 5) {
let domain = "localhost/url/";
let shortenURL = domain + data;
let newRow = `
<li>
<div class="link-icon"><img src="assets/images/url.png" class="logo-img"></div>
<div class="link-info">
<span class="short-link">${shortenURL}</span>
<span class="long-link">${urlInput.value}</span>
</div>
<button class="copy-btn"><img src="assets/images/copy.png"></button>
<button class="delete-btn"><img src="assets/images/delete.png"></button>
</li>
`;
linksList.insertAdjacentHTML('afterbegin', newRow);
urlInput.value = ""; // Clear the input field
location.reload(); // Reload the page after shortening
} else {
alert(data);
}
}
};
let formData = new FormData();
formData.append("full_url", urlInput.value);
xhr.send(formData);
};
// Handle copy button clicks
document.addEventListener('click', function(e) {
if (e.target.closest('.copy-btn')) {
const linkInfo = e.target.closest('li').querySelector('.short-link').textContent;
navigator.clipboard.writeText(linkInfo).catch(err => {
console.error('Failed to copy text: ', err);
});
}
// Handle delete button clicks
document.querySelectorAll(".delete-btn").forEach((deleteBtn) => {
deleteBtn.addEventListener("click", function () {
const linkItem = this.closest("li");
const shortenURL = linkItem.querySelector(".short-link").textContent;
let xhr = new XMLHttpRequest();
xhr.open("GET", `php/delete.php?id=${shortenURL.split('/').pop()}`, true);
xhr.onload = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
if (xhr.responseText === "success") {
linkItem.remove();
} else {
alert("Failed to delete the URL.");
}
}
};
xhr.send();
});
});
});

18
footer.php Normal file
View File

@@ -0,0 +1,18 @@
<link rel="stylesheet" href="assets/css/footer.css">
<footer>
<div class="footer-container">
<p>
<img src="assets/images/url.svg" class="footer-img">
<span style="font-size: 12px;color:#84819E;font-weight: 500; margin-left:-8px; margin-top: 5px; display: inline-block;">Xeorl</span>
<span style="font-size: 12px;color:#ABB2BF;font-weight: 500; margin-top: 5px; display: inline-block;">open source</span> <br>
<span style="font-size: 10px;color:#ABB2BF; display: block; margin-top: 12px;">Released under MIT License | Copyright © 2024</span>
</p>
<div class="footer-links">
<a href="#">Privacy</a>
<a href="#">Terms</a>
<a href="#">Contact</a>
</div>
</div>
</footer>
</body>
</html>

16
header.php Normal file
View File

@@ -0,0 +1,16 @@
<link rel="stylesheet" href="assets/css/header.css">
<header>
<div class="logo">
<img src="assets/images/url.png" alt="Xeorl Logo" class="logo-img">
<span>Xeorl</span>
</div>
<nav>
<ul>
<li><a href="index.php" class="<?php echo basename($_SERVER['PHP_SELF']) == 'index.php' ? 'active disabled' : ''; ?>">Home</a></li>
<li><a href="monetization.php" class="<?php echo basename($_SERVER['PHP_SELF']) == 'monetization.php' ? 'active disabled' : ''; ?>">Monetization</a></li>
<li><a href="pricing.php" class="<?php echo basename($_SERVER['PHP_SELF']) == 'pricing.php' ? 'active disabled' : ''; ?>">Pricing</a></li>
<li><a href="contact.php" class="<?php echo basename($_SERVER['PHP_SELF']) == 'contact.php' ? 'active disabled' : ''; ?>">Contact</a></li>
</ul>
</nav>
</header>
<script src="assets/js/header.js"></script>

50
home.php Normal file
View File

@@ -0,0 +1,50 @@
<?php include 'header.php'; ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Xeorl - Shorten your links</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/home.css">
</head>
<body>
<main>
<section class="shorten-section">
<h1>Open source inits.</h1>
<h2>Lovingly hand-crafted.</h2>
<p>Premium link shortening for use in web, iOS, Android, and<br>
desktop apps. Supported for urls. Completely open source, MIT<br>
licensed and built by <a href="https://www.xodivorce.in" target="_blank" class="custom-link">xodivorce</a>.</p>
<div class="shorten-form">
<input type="text" id="url-input" placeholder="Type a link...">
<button id="shorten-btn">SHORTEN</button>
</div>
<div class="shortened-links">
<h2>Your shortened links :</h2>
<ul id="links-list">
<li>
<div class="link-icon">
<img src="assets/images/url.png" class="logo-img">
</div>
<div class="link-info">
<span class="short-link">xeorl.com/WAXD</span>
<span class="long-link">https://www.example.com/very-long-url-that-needs-shortening</span>
</div>
<button class="copy-btn">
<img src="assets/images/copy.png">
</button>
<button class="delete-btn">
<img src="assets/images/delete.png">
</button>
</li>
</ul>
</div>
</section>
</main>
<?php include 'footer.php'; ?>
<script src="assets/js/home.js"></script>
</body>
</html>

104
index.php Normal file
View File

@@ -0,0 +1,104 @@
<?php
// Start session management
session_start();
// Include necessary files
include "header.php";
include "php/config.php";
// Set a cookie to track user visits or preferences
$cookie_name = "user_visited";
$cookie_value = "true";
$cookie_expire_time = time() + (86400 * 30); // Cookie expires in 30 days
setcookie($cookie_name, $cookie_value, $cookie_expire_time, "/"); // The "/" makes the cookie available across the entire website
// Check if the cookie exists
if (isset($_COOKIE[$cookie_name])) {
// Cookie exists, you can execute specific logic like tracking the visit
} else {
// Cookie does not exist, handle the first-time visit
}
// Set session data for the user
$_SESSION['user'] = "unique_user_id"; // Store unique user ID in session
// Retrieve and use session data
if (isset($_SESSION['user'])) {
$user_id = $_SESSION['user'];
// Do something with $user_id, like loading user-specific data
}
// Initialize the shortened URL variable
$new_url = "";
// Check if there's a GET request and process the shortened URL
if (isset($_GET)) {
foreach ($_GET as $key => $val) {
$u = mysqli_real_escape_string($conn, $key);
$new_url = str_replace('/', '', $u);
}
// Query the database for the full URL associated with the shortened URL
$sql = mysqli_query($conn, "SELECT full_url FROM url WHERE shorten_url = '{$new_url}'");
if (mysqli_num_rows($sql) > 0) {
// Increment the click count for the shortened URL
$sql2 = mysqli_query($conn, "UPDATE url SET clicks = clicks + 1 WHERE shorten_url = '{$new_url}'");
if ($sql2) {
// Fetch the full URL and redirect to it
$full_url = mysqli_fetch_assoc($sql);
header("Location:" . $full_url['full_url']);
exit(); // Stop further script execution after redirection
}
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Xeorl - Shorten your links</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/home.css">
</head>
<body>
<main>
<section class="shorten-section">
<h1>Open source inits.</h1>
<h2>Lovingly hand-crafted.</h2>
<p>Premium link shortening for use in web, iOS, Android, and<br> desktop apps. Supported for urls. Completely open source, MIT<br> licensed and built by <a href="https://www.xodivorce.in" target="_blank" class="custom-link">xodivorce</a>.</p>
<div class="shorten-form">
<input type="text" id="url-input" placeholder="Type a link...">
<button id="shorten-btn">SHORTEN</button>
</div>
<div class="shortened-links">
<h2>Your shortened links :</h2>
<ul id="links-list">
<?php
$sql2 = mysqli_query($conn, "SELECT * FROM url ORDER BY id DESC");
if (mysqli_num_rows($sql2) > 0) {
while ($row = mysqli_fetch_assoc($sql2)) {
$short_url = $domain . $row['shorten_url'];
echo '<li>';
echo '<div class="link-icon"><img src="assets/images/url.png" class="logo-img"></div>';
echo '<div class="link-info">';
echo '<span class="short-link">' . $short_url . '</span>';
echo '<span class="long-link">' . $row['full_url'] . '</span>';
echo '</div>';
echo '<button class="copy-btn"><img src="assets/images/copy.png"></button>';
echo '<button class="delete-btn"><img src="assets/images/delete.png"></button>';
echo '</li>';
}
}
?>
</ul>
</div>
</section>
</main>
<?php include 'footer.php'; ?>
<script src="assets/js/home.js"></script>
</body>
</html>

20
php/config.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
/* if you're working on localhost then you don't need to change anything
but if you're thinking to upload it to live server then you've to edit something
1. Paste your website url with forward slash(/) in the domain variable, you don't need
to write https://wwww. before the domain name if you have domain redirection setup
2. Change user, pass, db values accordingly mentioned in the comments below
3. Go to JavaScript file and search this keyword - let domain - then paste your url there
4. After all changes you've to wait because javascript file save changes may take time to reflect */
$domain = "https://localhost/web-Projects/url/"; //like this: codingnepalweb.com/
$host = "localhost";
$user = "root"; //Database username
$pass = ""; //Database password
$db = "urlShortener"; //Database name
$conn = mysqli_connect($host, $user, $pass, $db);
if(!$conn){
echo "Database connection error".mysqli_connect_error();
}
?>

15
php/delete.php Normal file
View File

@@ -0,0 +1,15 @@
<?php
include "config.php";
if(isset($_GET['id'])){
$delete_id = mysqli_real_escape_string($conn, $_GET['id']);
$sql = mysqli_query($conn, "DELETE FROM url WHERE shorten_url = '{$delete_id}'");
if($sql){
echo "success";
} else {
echo "error";
}
} else {
echo "error";
}
?>

23
php/url-controll.php Normal file
View File

@@ -0,0 +1,23 @@
<?php
include "config.php";
$full_url = mysqli_real_escape_string($conn, $_POST['full_url']);
if(!empty($full_url) && filter_var($full_url, FILTER_VALIDATE_URL)){
$ran_url = substr(md5(microtime()), rand(0, 26), 5);
$sql = mysqli_query($conn, "SELECT * FROM url WHERE shorten_url = '{$ran_url}'");
if(mysqli_num_rows($sql) > 0){
echo "Something went wrong. Please generate again!";
}else{
$sql2 = mysqli_query($conn, "INSERT INTO url (full_url, shorten_url, clicks)
VALUES ('{$full_url}', '{$ran_url}', '0')");
if($sql2){
$sql3 = mysqli_query($conn, "SELECT shorten_url FROM url WHERE shorten_url = '{$ran_url}'");
if(mysqli_num_rows($sql3) > 0){
$shorten_url = mysqli_fetch_assoc($sql3);
echo $shorten_url['shorten_url'];
}
}
}
}else{
echo "$full_url - This is not a valid URL!";
}
?>

38
script.js Normal file
View File

@@ -0,0 +1,38 @@
const form = document.querySelector(".wrapper form"),
fullURL = form.querySelector("input"),
shortenBtn = form.querySelector("form button"),
urlsArea = document.querySelector(".urls-area");
form.onsubmit = (e) => {
e.preventDefault();
};
shortenBtn.onclick = () => {
let xhr = new XMLHttpRequest();
xhr.open("POST", "php/url-controll.php", true);
xhr.onload = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
let data = xhr.response;
if (data.length <= 5) {
// Example of setting the shortened URL directly to the list
let domain = "localhost/url/";
let shortenURL = domain + data;
// Create a new row for the URL and append it to the list
let newRow = `
<div class="data">
<li><a href="${shortenURL}" target="_blank">${shortenURL}</a></li>
<li>${fullURL.value}</li>
<li>0</li>
<li><a href="php/delete.php?id=${data}">Delete</a></li>
</div>
`;
urlsArea.insertAdjacentHTML('afterbegin', newRow);
} else {
alert(data);
}
}
};
let formData = new FormData(form);
xhr.send(formData);
};

255
style.css Normal file
View File

@@ -0,0 +1,255 @@
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;300;400;500;600;700&display=swap');
*{
margin: 0;
padding: 0;
box-sizing: border-box;
text-decoration: none;
font-family: 'Poppins', sans-serif;
}
body{
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: #20B2AA;
padding: 0 10px;
}
.wrapper{
background: #fff;
padding: 20px;
width: 800px;
border-radius: 5px;
box-shadow: 0px 5px 10px rgba(0,0,0,0.1);
}
::selection{
background: rgba(23,162,184,0.3);
}
.wrapper form{
height: 50px;
width: 100%;
display: flex;
position: relative;
align-items: center;
}
form .url-icon{
position: absolute;
width: 50px;
text-align: center;
font-size: 23px;
color: #c4c4c4;
pointer-events: none;
}
form input:valid ~ .url-icon{
color: #20B2AA;
}
form input{
height: 100%;
width: 100%;
outline: none;
padding: 0 120px 0 45px;
font-size: 20px;
caret-color: #20B2AA;
border: 2px solid #ddd;
border-radius: 5px;
transition: all 0.1s ease;
}
form input:valid{
border-color: #20B2AA;
}
form input::placeholder{
color: #c4c4c4;
}
form input:focus::placeholder{
color: #d9d9d9;
}
form button{
position: absolute;
right: 6px;
padding: 5px 15px;
font-size: 18px;
border-radius: 5px;
border: none;
outline: none;
background: #20B2AA;
color: #fff;
cursor: pointer;
transition: all 0.3s ease;
}
form button:hover{
background: #1fada6;
}
.wrapper form button{
opacity: 0;
pointer-events: none;
}
.wrapper form input:valid ~ button{
opacity: 1;
pointer-events: auto;
}
.wrapper a{
color: #000;
}
.wrapper .statistics{
margin: 20px 0;
display: flex;
padding-right: 5px;
align-items: center;
justify-content: space-between;
}
.statistics span{
font-size: 17px;
}
.statistics span span{
font-weight: 500;
}
.statistics a:hover{
color: #20B2AA;
}
.wrapper .urls-area{
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 5px;
max-height: 400px;
overflow-y: scroll;
}
.urls-area::-webkit-scrollbar{
width: 0px;
}
.urls-area :is(.title, .data){
display: flex;
width: 100%;
justify-content: space-between;
}
.urls-area li{
width: 100%;
list-style: none;
border-right: 1px solid #ddd;
}
.urls-area li:last-child{
border-right: 0px;
}
.urls-area .title li{
text-align: center;
background: #f2f2f2;
padding: 10px 0;
}
.urls-area .data li{
padding: 8px 10px;
display: flex;
align-items: center;
justify-content: center;
word-break: break-all;
}
.urls-area .data li:last-child a{
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.urls-area .data li a:hover{
color: #20B2AA;
text-decoration: underline;
}
.urls-area .data li:last-child a:hover{
text-decoration: none;
}
.urls-area .data:nth-child(odd){
background: #f2f2f2;
}
.urls-area li:nth-child(1){
max-width: 30%;
}
.urls-area li:nth-child(2){
max-width: 45%;
}
.urls-area li:nth-child(3){
max-width: 11%;
}
.urls-area li:nth-child(4){
max-width: 14%;
}
.blur-effect{
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
backdrop-filter: blur(2px);
background: rgba(0,0,0,0.01);
display: none;
}
.popup-box{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.9);
background: #fff;
padding: 25px;
max-width: 480px;
width: 100%;
border-radius: 5px;
box-shadow: 0px 5px 10px rgba(0,0,0,0.1);
opacity: 0;
visibility: hidden;
pointer-events: none;
transition: all 0.3s ease;
}
.popup-box.show{
opacity: 1;
pointer-events: auto;
visibility: visible;
transform: translate(-50%, -50%) scale(1);
}
.popup-box .info-box{
color: #0f5753;
background: #bef4f1;
border: 1px solid #7de8e3;
padding: 10px;
text-align: center;
font-size: 17px;
border-radius: 5px;
}
.popup-box .info-box.error{
color: #721c24;
background: #f8d7da;
border-color: #f5c6cb;
}
.popup-box form{
margin-top: 10px;
position: relative;
}
.popup-box form label{
font-size: 18px;
}
.popup-box form .copy-icon{
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-100%);
font-size: 20px;
cursor: pointer;
}
.copy-icon:hover{
color: #20B2AA;
}
.popup-box form input{
height: 45px;
padding: 0 35px 0 15px;
margin-top: 3px;
border: 1px solid #ccc;
}
.popup-box form input:focus{
border-color: #20B2AA;
}
.popup-box form button{
width: 100%;
height: 45px;
position: relative;
right: 0;
font-size: 20px;
margin-top: 10px;
}

422
unzipper.php Normal file
View File

@@ -0,0 +1,422 @@
<?php
/**
* The Unzipper extracts .zip or .rar archives and .gz files on webservers.
* It's handy if you do not have shell access. E.g. if you want to upload a lot
* of files (php framework or image collection) as an archive to save time.
* As of version 0.1.0 it also supports creating archives.
*
* @author Andreas Tasch, at[tec], attec.at
* @license GNU GPL v3
* @package attec.toolbox
* @version 0.1.1
*/
define('VERSION', '0.1.1');
$timestart = microtime(TRUE);
$GLOBALS['status'] = array();
$unzipper = new Unzipper;
if (isset($_POST['dounzip'])) {
// Check if an archive was selected for unzipping.
$archive = isset($_POST['zipfile']) ? strip_tags($_POST['zipfile']) : '';
$destination = isset($_POST['extpath']) ? strip_tags($_POST['extpath']) : '';
$unzipper->prepareExtraction($archive, $destination);
}
if (isset($_POST['dozip'])) {
$zippath = !empty($_POST['zippath']) ? strip_tags($_POST['zippath']) : '.';
// Resulting zipfile e.g. zipper--2016-07-23--11-55.zip.
$zipfile = 'zipper-' . date("Y-m-d--H-i") . '.zip';
Zipper::zipDir($zippath, $zipfile);
}
$timeend = microtime(TRUE);
$time = round($timeend - $timestart, 4);
/**
* Class Unzipper
*/
class Unzipper {
public $localdir = '.';
public $zipfiles = array();
public function __construct() {
// Read directory and pick .zip, .rar and .gz files.
if ($dh = opendir($this->localdir)) {
while (($file = readdir($dh)) !== FALSE) {
if (pathinfo($file, PATHINFO_EXTENSION) === 'zip'
|| pathinfo($file, PATHINFO_EXTENSION) === 'gz'
|| pathinfo($file, PATHINFO_EXTENSION) === 'rar'
) {
$this->zipfiles[] = $file;
}
}
closedir($dh);
if (!empty($this->zipfiles)) {
$GLOBALS['status'] = array('info' => '.zip or .gz or .rar files found, ready for extraction');
}
else {
$GLOBALS['status'] = array('info' => 'No .zip or .gz or rar files found. So only zipping functionality available.');
}
}
}
/**
* Prepare and check zipfile for extraction.
*
* @param string $archive
* The archive name including file extension. E.g. my_archive.zip.
* @param string $destination
* The relative destination path where to extract files.
*/
public function prepareExtraction($archive, $destination = '') {
// Determine paths.
if (empty($destination)) {
$extpath = $this->localdir;
}
else {
$extpath = $this->localdir . '/' . $destination;
// Todo: move this to extraction function.
if (!is_dir($extpath)) {
mkdir($extpath);
}
}
// Only local existing archives are allowed to be extracted.
if (in_array($archive, $this->zipfiles)) {
self::extract($archive, $extpath);
}
}
/**
* Checks file extension and calls suitable extractor functions.
*
* @param string $archive
* The archive name including file extension. E.g. my_archive.zip.
* @param string $destination
* The relative destination path where to extract files.
*/
public static function extract($archive, $destination) {
$ext = pathinfo($archive, PATHINFO_EXTENSION);
switch ($ext) {
case 'zip':
self::extractZipArchive($archive, $destination);
break;
case 'gz':
self::extractGzipFile($archive, $destination);
break;
case 'rar':
self::extractRarArchive($archive, $destination);
break;
}
}
/**
* Decompress/extract a zip archive using ZipArchive.
*
* @param $archive
* @param $destination
*/
public static function extractZipArchive($archive, $destination) {
// Check if webserver supports unzipping.
if (!class_exists('ZipArchive')) {
$GLOBALS['status'] = array('error' => 'Error: Your PHP version does not support unzip functionality.');
return;
}
$zip = new ZipArchive;
// Check if archive is readable.
if ($zip->open($archive) === TRUE) {
// Check if destination is writable
if (is_writeable($destination . '/')) {
$zip->extractTo($destination);
$zip->close();
$GLOBALS['status'] = array('success' => 'Files unzipped successfully');
}
else {
$GLOBALS['status'] = array('error' => 'Error: Directory not writeable by webserver.');
}
}
else {
$GLOBALS['status'] = array('error' => 'Error: Cannot read .zip archive.');
}
}
/**
* Decompress a .gz File.
*
* @param string $archive
* The archive name including file extension. E.g. my_archive.zip.
* @param string $destination
* The relative destination path where to extract files.
*/
public static function extractGzipFile($archive, $destination) {
// Check if zlib is enabled
if (!function_exists('gzopen')) {
$GLOBALS['status'] = array('error' => 'Error: Your PHP has no zlib support enabled.');
return;
}
$filename = pathinfo($archive, PATHINFO_FILENAME);
$gzipped = gzopen($archive, "rb");
$file = fopen($destination . '/' . $filename, "w");
while ($string = gzread($gzipped, 4096)) {
fwrite($file, $string, strlen($string));
}
gzclose($gzipped);
fclose($file);
// Check if file was extracted.
if (file_exists($destination . '/' . $filename)) {
$GLOBALS['status'] = array('success' => 'File unzipped successfully.');
// If we had a tar.gz file, let's extract that tar file.
if (pathinfo($destination . '/' . $filename, PATHINFO_EXTENSION) == 'tar') {
$phar = new PharData($destination . '/' . $filename);
if ($phar->extractTo($destination)) {
$GLOBALS['status'] = array('success' => 'Extracted tar.gz archive successfully.');
// Delete .tar.
unlink($destination . '/' . $filename);
}
}
}
else {
$GLOBALS['status'] = array('error' => 'Error unzipping file.');
}
}
/**
* Decompress/extract a Rar archive using RarArchive.
*
* @param string $archive
* The archive name including file extension. E.g. my_archive.zip.
* @param string $destination
* The relative destination path where to extract files.
*/
public static function extractRarArchive($archive, $destination) {
// Check if webserver supports unzipping.
if (!class_exists('RarArchive')) {
$GLOBALS['status'] = array('error' => 'Error: Your PHP version does not support .rar archive functionality. <a class="info" href="http://php.net/manual/en/rar.installation.php" target="_blank">How to install RarArchive</a>');
return;
}
// Check if archive is readable.
if ($rar = RarArchive::open($archive)) {
// Check if destination is writable
if (is_writeable($destination . '/')) {
$entries = $rar->getEntries();
foreach ($entries as $entry) {
$entry->extract($destination);
}
$rar->close();
$GLOBALS['status'] = array('success' => 'Files extracted successfully.');
}
else {
$GLOBALS['status'] = array('error' => 'Error: Directory not writeable by webserver.');
}
}
else {
$GLOBALS['status'] = array('error' => 'Error: Cannot read .rar archive.');
}
}
}
/**
* Class Zipper
*
* Copied and slightly modified from http://at2.php.net/manual/en/class.ziparchive.php#110719
* @author umbalaconmeogia
*/
class Zipper {
/**
* Add files and sub-directories in a folder to zip file.
*
* @param string $folder
* Path to folder that should be zipped.
*
* @param ZipArchive $zipFile
* Zipfile where files end up.
*
* @param int $exclusiveLength
* Number of text to be exclusived from the file path.
*/
private static function folderToZip($folder, &$zipFile, $exclusiveLength) {
$handle = opendir($folder);
while (FALSE !== $f = readdir($handle)) {
// Check for local/parent path or zipping file itself and skip.
if ($f != '.' && $f != '..' && $f != basename(__FILE__)) {
$filePath = "$folder/$f";
// Remove prefix from file path before add to zip.
$localPath = substr($filePath, $exclusiveLength);
if (is_file($filePath)) {
$zipFile->addFile($filePath, $localPath);
}
elseif (is_dir($filePath)) {
// Add sub-directory.
$zipFile->addEmptyDir($localPath);
self::folderToZip($filePath, $zipFile, $exclusiveLength);
}
}
}
closedir($handle);
}
/**
* Zip a folder (including itself).
*
* Usage:
* Zipper::zipDir('path/to/sourceDir', 'path/to/out.zip');
*
* @param string $sourcePath
* Relative path of directory to be zipped.
*
* @param string $outZipPath
* Relative path of the resulting output zip file.
*/
public static function zipDir($sourcePath, $outZipPath) {
$pathInfo = pathinfo($sourcePath);
$parentPath = $pathInfo['dirname'];
$dirName = $pathInfo['basename'];
$z = new ZipArchive();
$z->open($outZipPath, ZipArchive::CREATE);
$z->addEmptyDir($dirName);
if ($sourcePath == $dirName) {
self::folderToZip($sourcePath, $z, 0);
}
else {
self::folderToZip($sourcePath, $z, strlen("$parentPath/"));
}
$z->close();
$GLOBALS['status'] = array('success' => 'Successfully created archive ' . $outZipPath);
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>File Unzipper + Zipper</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
<!--
body {
font-family: Arial, sans-serif;
line-height: 150%;
}
label {
display: block;
margin-top: 20px;
}
fieldset {
border: 0;
background-color: #EEE;
margin: 10px 0 10px 0;
}
.select {
padding: 5px;
font-size: 110%;
}
.status {
margin: 0;
margin-bottom: 20px;
padding: 10px;
font-size: 80%;
background: #EEE;
border: 1px dotted #DDD;
}
.status--ERROR {
background-color: red;
color: white;
font-size: 120%;
}
.status--SUCCESS {
background-color: green;
font-weight: bold;
color: white;
font-size: 120%
}
.small {
font-size: 0.7rem;
font-weight: normal;
}
.version {
font-size: 80%;
}
.form-field {
border: 1px solid #AAA;
padding: 8px;
width: 280px;
}
.info {
margin-top: 0;
font-size: 80%;
color: #777;
}
.submit {
background-color: #378de5;
border: 0;
color: #ffffff;
font-size: 15px;
padding: 10px 24px;
margin: 20px 0 20px 0;
text-decoration: none;
}
.submit:hover {
background-color: #2c6db2;
cursor: pointer;
}
-->
</style>
</head>
<body>
<p class="status status--<?php echo strtoupper(key($GLOBALS['status'])); ?>">
Status: <?php echo reset($GLOBALS['status']); ?><br/>
<span class="small">Processing Time: <?php echo $time; ?> seconds</span>
</p>
<form action="" method="POST">
<fieldset>
<h1>Archive Unzipper</h1>
<label for="zipfile">Select .zip or .rar archive or .gz file you want to extract:</label>
<select name="zipfile" size="1" class="select">
<?php foreach ($unzipper->zipfiles as $zip) {
echo "<option>$zip</option>";
}
?>
</select>
<label for="extpath">Extraction path (optional):</label>
<input type="text" name="extpath" class="form-field" />
<p class="info">Enter extraction path without leading or trailing slashes (e.g. "mypath"). If left empty current directory will be used.</p>
<input type="submit" name="dounzip" class="submit" value="Unzip Archive"/>
</fieldset>
<fieldset>
<h1>Archive Zipper</h1>
<label for="zippath">Path that should be zipped (optional):</label>
<input type="text" name="zippath" class="form-field" />
<p class="info">Enter path to be zipped without leading or trailing slashes (e.g. "zippath"). If left empty current directory will be used.</p>
<input type="submit" name="dozip" class="submit" value="Zip Archive"/>
</fieldset>
</form>
<p class="version">Unzipper version: <?php echo VERSION; ?></p>
</body>
</html>

60
url.sql Normal file
View File

@@ -0,0 +1,60 @@
-- phpMyAdmin SQL Dump
-- version 5.0.4
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: Mar 18, 2021 at 10:27 AM
-- Server version: 10.4.17-MariaDB
-- PHP Version: 7.3.26
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `urlshortener`
--
-- --------------------------------------------------------
--
-- Table structure for table `url`
--
CREATE TABLE `url` (
`id` int(11) NOT NULL,
`shorten_url` varchar(200) NOT NULL,
`full_url` varchar(1000) NOT NULL,
`clicks` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `url`
--
ALTER TABLE `url`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `url`
--
ALTER TABLE `url`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=53;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;