Tumgik
#wp admin pass
f1 · 1 year
Text
Perez passes Leclerc for sprint race win Verstappen third in damaged car | 2023 Azerbaijan Grand Prix
Sergio Perez https://www.racefans.net/wp-admin/post.php?post=504479&action=editSergio Perez took victory in the sprint race for the Azerbaijan Grand Prix after overtaking Charles Leclerc mid-way through the race and pulling away from the Ferrari driver. The Red Bull driver used DRS to pass Leclerc for the lead along the pit straight and then gradually opened up the gap to win by four seconds. Leclerc held off Max Verstappen for second place after the Red Bull driver suffered damaged from opening lap contact with George Russell. Leclerc lined up on pole position for the first sprint race of the season and when the lights went out the Ferrari leapt out into the lead of the race with Perez settling into second place behind. Verstappen came under pressure from George Russell behind with the Mercedes driver pulling ahead of the Red Bull on the run to turn three. Back in the pack, Yuki Tsunoda struck the barrier at the kink of turn 13, losing the tyre from his wheel. As the AlphaTauri recovered to the pits with damage, the Virtual Safety Car was deployed with the remains of Tsunoda’s tyre on the circuit on the entrance of turn 16. Tsunoda pitted and rejoined with his car still clearly damaged from his collision with the wall, earning an investigation from the stewards after the race for being released in an unsafe condition. With drivers complaining of debris on the track, the Virtual Safety Car was upgraded to a full Safety Car. The race restarted at the end of lap five, with Leclerc leading the field away from Perez, Russell and Verstappen. Russell was easily passed by Verstappen at the restart, the Red Bull diving to the inside into the first corner to move back into third. At the end of the first green flag lap, DRS was enabled for the first time in the race. Perez quickly began to put Leclerc under pressure out front and managed to slip by the Ferrari into the lead at the start of lap eight, before soon pulling clear of DRS range of the chasing Ferrari. Leclerc kept Perez’s lead to around a second until the leader began picking up the pace with around five laps remaining, building up his advantage to over three seconds. Verstappen pursued the Ferrari ahead of him, but despite sitting within a second of Leclerc he never got close enough to attempt a pass. Perez continued to eke out his advantage and ticked off the remaining laps to secure the victory by just over four seconds at the chequered flag. Leclerc finished six tenths of a second ahead of Verstappen in second place, with Russell a further three seconds behind in fourth. Carlos Sainz Jnr finished in fifth, ahead of Alonso, Hamilton and Lance Stroll claiming the final point in eighth place. Alexander Albon just missed out on points in ninth with Oscar Piastri completing the top ten. Advert | Become a RaceFans supporter and go ad-free 2023 Azerbaijan Grand Prix Browse all 2023 Azerbaijan Grand Prix articles via RaceFans - Independent Motorsport Coverage https://www.racefans.net/
2 notes · View notes
nearme-job · 23 hours
Text
https://www.nearmejob.in/wp-admin/post.php?post=402&action=edit
Ahmedabad 8th Pass Jobs & Salaries
Discover salaries! 8th Pass jobs & pay rates in Ahmedabad.
0 notes
Photo
Tumblr media
Pass the Certified Nursing Assistant (CNA) evaluation with Nurse Eunice and Florida Training Academy. 19659002 Hyperlinks: Class Schedules and Registration: http://www.FLtraining.com 19659004 Nurse Eunice’s Online CNA Exam Prep Course (readily available 3/3/2024) www.NurseEunice.com 19659005 Nurse Eunice’s YouTube Channel ** Subscribe to my Channel ** http://www.YouTube.com/EuniceMathis Florida Training Academy’s YouTube Channel http://www.YouTube.com/FloridaTraining Email Address: [email protected] 19659010…
0 notes
wpeventmanagersblog · 7 months
Text
How to Set up Stripe in WordPress- Detailed Guide
If you have a WordPress online shop or if you want to monetize your WordPress website then you must have a secured payment gateway to manage transactions safely and smoothly. Stripe payments can be a great option for you in this regard.
One of the biggest advantages of Stripe is that it comes with lower transaction cost and it is also preferred by developers due to its flexible API. Besides this, it is also easy for users to set up Stripe in WordPress sites. In this article we have shared the steps in details that you need to pass through to set up Stripe in WordPress sites.
Tumblr media
There are multiple ways through which you can accept payments to your WordPress sites and in this article we have specially discussed how you can set up Stripe on your WordPress events website through a WordPress Stripe payment plugin.
Besides selling event tickets, you can monetize your events website in different ways. For example, as an events website owner you can invite other event organizers to post their events and sell tickets on your website and charge them accordingly. Here, you can accept the payments through Stripe.
How to set up Stripe in WordPress using a WordPress plugin?
This method is especially suitable for those who are not looking to build a full fledged eCommerce store and just want to sell only one type of product like event tickets.
Tumblr media
Follow the below mentioned steps to set up Stripe for WordPress sites:
Step 1: Select a suitable Stripe payment plugin for WordPress
To get a detailed idea about Stripe payment plugins for WordPress, read our previous blog “5 best Stripe Payment Plugins for WordPress in 2023”.
We recommend the Stripe Split Payments plugin from WP Event Manager for setting up Stripe on your WordPress site.
It has the right features that fulfill all your unique business requirements.
How does the Stripe Split Payment work?
The Stripe Split Payment automatically distributes the event ticket revenue between the organizer and the website owner based on the percentage or amount that has been mentioned by the admin.
Tumblr media
Some of the key features of the Stripe Split Payment plugin include:
The plugin allows a safe and secured transaction between the admin and event organizer. 
Event organizers can easily connect their accounts with Stripe through the Frontend. 
Easy plugin set up. 
Fully automated process.
How to get started with the Stripe Payment plugin offered by WP Event Manager?
Download and install the core plugin which is absolutely free. 
Purchase the Stripe Split Payment plugin. You can visit the pricing page for the details of their pricing structure. 
Finally install the premium WordPress payment plugin and start working with it.
Tumblr media
Step 2: Connect Stripe with your WordPress
You need to connect your Stripe account with WordPress to work with the plugin.
Here are the steps you need to take to connect your Stripe account with WordPress:
Login to your Stripe account https://dashboard.stripe.com/login.
After logging in, click on the Developers option present at the top right corner of the page. 
Click on the API keys option present under the Developers option. 
Then enable the “View test data” option. 
After enabling the “View test data” option, you can easily find the following.
Publishable key: copy the publishable key from here. 
Secret key: If the secret key is created already then you only need to click on the “Reveal test key” option but if the key is not created then you need to click on the “Create restricted key” option.
You will be redirected to a page where you need to add the key name and make changes in the Permissions and Connect Permissions sections as per your requirements. Then press the “create key” option.
Then you need to go to the Stipe page once again and click on the Settings option, present at the top right corner of the page and follow the below mentioned steps:
Go to Connect.
Choose the Settings option.
Scroll down to the integration section where you can get the Test mode client ID. 
Make sure that the Oauth for Standard account option is enabled. 
For direction, click on the Add URL option and Set the Website URL as http://www.example.com/
Note: Please set a default URL among the various URLs set by you for redirection. This can be done from the URL section.
Here, you have two keys for the client_Id that are to be used according to the mode –
Development mode – This client_id is to be used when your site is in the testing mode.
Product mode – This client_id is to be used when your site is in the live mode.
Step 4: Settings at the Admin Panel
After setting up a Stripe Account and obtaining the Keys, an admin needs to add these details to the Admin Panel.
Go to wp-admin. 
Click on WooCommerce. 
Choose the Settings option from the dropdown menu. 
Click on the Payments tab. 
Fill up the details as mentioned below:
Enable/Disable Stripe: Tick mark the option to enable Stripe
Stripe getaway title: Put the name of the Stripe gateway that will be shown in the checkout page.
Enter your display details settings:
Enable Test Mode: Enable this option to enable the Test mode. 
Test Client ID: Paste the test client id here that we have generated in the Stripe Connect segment. 
Test Publishable key: Paste the test publishable key here that we have generated in the Stripe Connect segment. 
Test secret key: Paste the test secret key here that we have generated in the Stripe Connect segment.
Configure other settings:
Enable shipping address: if you enable this option, the shipping address will be sent to Stripe. 
Loggin: if you enable this option, the debug messages will be saved to WooCommerce system status log.
Your Stripe account will be successfully connected to your WordPress. Follow the above mentioned steps to successfully initiate Stripe WordPress setup.
Stripe is also included in the list of popular payment gateways that are supported by WooCommerce and WP Event Manager supports WooCommerce payments. The Sell tickets addon lets users accept payments for their tickets through WooCommerce which again means that you can easily accept payments through Stripe.
Setting up Stripe on your WordPress website is easy when you have the support of a plugin like the Stripe Split Payments. All you need to do is to follow the above mentioned steps and you are ready to work with it and enjoy the benefits. To know more about Stripe Split Payment plugin functionalities, click here.
FAQs on Stripe Payment Gateway
1. Does Stripe charge a monthly fee?
Stripe does not ask for any monthly or annual fee to its users. Instead the Stripe fee is based on transactions. For online stores, businesses need to bear 2.9% plus 30 cents per transaction.
2. Is Stripe free to set up?
Stripe is absolutely free to set up but Stripe fees are based on transactions.
0 notes
gslin · 10 months
Text
0 notes
acupunctureworksllc · 2 years
Text
A Taste of Summer
Summer brings with it a variety of vegetables and fruits that aren’t available during the rest of the year. Two of the most abundant ingredients are tomatoes and zucchini. Here’s a great recipe that combines both for a dish you can make at home or share at a summer BBQ. This zucchini and tomato bake only takes minutes to prep and can help you use those vegetables before they spoil.
The ingredient list is simple:
3 medium zucchinis, chopped
1 pint of cherry tomatoes, halved) If you want to really be fancy, use the multi-colored tomatoes
2 cloves of minced garlic
Extra-virgin olive oil for a final drizzle
Kosher salt and freshly ground black pepper
1/3 cup of freshly grated parmesan cheese
2 tablespoons of basil, torn for garnish
And putting this dish together is quick and simple. Preheat your oven to 350 degrees. In a large bowl, combine the chopped zucchini, halved tomatoes, garlic, olive oil drizzle, salt and pepper to taste and mix everything until it is well combined. Pour vegetables in a small baking dish and sprinkle with parmesan. Bake 35 minutes until golden brown and delicious! Add the basil garnish and serve. 
Don’t let summer pass without making this dish that combines two of summer’s greatest culinary gifts. 
A Taste of Summer was last modified: June 13th, 2022 by admin
The post A Taste of Summer appeared first on Acupuncture Works, LLC.
https://acupunctureworksllclynchburg.com/wp-content/uploads/2022/06/tomato-zucchini-hwn.jpg https://acupunctureworksllclynchburg.com/health-well-news/a-taste-of-summer/
0 notes
mahmudparvez · 5 years
Text
Fix, reset wp pass, recovery wp admin login access
Fix, reset wp pass, recovery wp admin login access
Are you Looking for fixing your wp-admin pass and username recovery?
I am here to help you!
Tumblr media
Bugs fixing:: 
Recovery WordPress pass or username 
Reset pass 
Forgot pass to a new pass or user setup
Admin login reset
Etc.
Extra:
Responsive issue
CSS issue
Design issue
Fatal error
Contact form issue
Blank site error
Etc.
Thanks!
View On WordPress
1 note · View note
Text
Trump will deliver killing blow to the USPS
Tumblr media
The USPS is about to declare bankruptcy. It's at the center of the longstanding plans for disaster recover and has been since the Cold War. It's the only institution that could (for example) deliver covid meds to every home in America in one day.
https://pluralistic.net/2020/03/25/national-emergency-library/#going-postal
But Congress has decided not to bail out the postal service, despite Art 1, Sec 8 of the US Constitution: "To establish Post Offices and post Roads."
Maybe it's because without a USPS we couldn't have a postal vote in 2020?
https://pluralistic.net/2020/03/27/just-asking-questions/#save-usps
The proximate cause of the post office's bankruptcy is the pandemic, but that is merely the finishing blow. The USPS was murdered in 2006, when Congress passed the Postal Accountability and Enhancement Act.
https://www.nakedcapitalism.com/2020/04/will-the-united-states-post-office-become-a-victim-of-covid19.html
The Act gave the USPS a mere 10 years to "prefund its future health care benefit payments to retirees for the next 75 years." That is, to set aside cash to pay medical bills for future employees who hadn't been born yet.
https://www.govtrack.us/congress/bill.xpd?bill=h109-6407
The Act gave the USPS a mere 10 years to "prefund its future health care benefit payments to retirees for the next 75 years." That is, to set aside cash to pay medical bills for future employees who hadn't been born yet.
https://www.govtrack.us/congress/bill.xpd?bill=h109-6407
The USPS's murder is straight out of the neoliberal playbook: "1 Defund, 2 claim crisis, 3 call for privatizatization, 4 profit!"
As Lambert Strether points out, it was a bipartisan act of murder, cosponored by the "centrist" Democrat Henry Waxman.
Killing the USPS looms large in the Trump admin's (nonmetaphorical, actual) privatization playbook, "Delivering Government Solutions in the 21st Century Reform Plan and Reorganization Recommendations":
https://www.whitehouse.gov/wp-content/uploads/2018/06/Government-Reform-and-Reorg-Plan.pdf
The proposals are for USPS to become a Wework clone or franchisee, but not to become a publicly owned bank - a common line of business for other nations' postal services, natural based on the amounts of cash they handle.
The USPS is the nation's second largest employer of veterans, with 630,000 employees. Trump is about to allow it to collapse so that UPS, Fedex and other private firms can skim off the most profitable parts of its business and leave rural Americans totally isolated.
The loss of the USPS would mean the loss of the last truly universal federal program in America and would unduly hammer the people whom Trump claims to love -- veterans and rural voters.
https://twitter.com/lildipshit3/status/1248741868440940544
48K notes · View notes
carotidartistry · 4 years
Text
COVID and the Arts
The existence of algorithm-driven, non-chronological "timelines" is very bizarre right now. On my Facebook feed, I see posts from March 10 talking about starting the second week of previews or celebrating good box office returns. On March 12, my job ceased to exist, as did the jobs of hundreds upon hundreds of people as an entire industry shuttered over the course of one day.
The cancellations and closing of events and arts/entertainment venues, while important for public health, have left many people (who earn on a gig basis rather than salary) very suddenly and entirely without expected income. There is no work-from-home option, just their job disappearing entirely. Some people will be able to collect unemployment insurance, but many won't even get that, as they work as independent contractors who are paid a fee for work delivered or vend their goods directly to customers at such events.
This is a tough time for arts/events organizations and those who work them (which includes not just artists but all of the ushers, custodians, etc. whose work is tied to the event itself). I'm compiling ways to support those who have been impacted (pass-the-hats for donating to individuals, funds that are accepting donations, ways to purchase people's goods/services, etc.) and resources for those who have been impacted. The industry community is coming together in a heartening way right now, but it would mean a great deal to me if those not in the industry could take a moment to glance through and maybe even to share this information. Even if you can't make any sort of donation yourself, it means something to have this hardship be seen and acknowledged.
Additionally, if you have tickets to events that have been canceled and don't immediately need your funds returned, I encourage you to wait a bit before reaching out to the theater/venue/etc.. Box office workers have been overwhelmed. And particularly if it was a ticket for a non-profit or grassroots organization, if it's possible, I'd encourage people to consider donating the cost of their ticket rather than demanding a refund.
While I'm aware that there are many people in many sectors taking a hit right now, I am putting my focus on where I am and would like to keep that the focus here. Please share any relevant updates, additional resources, etc..
Support Those Who Have Been Impacted
A general pass-the-hat for individual theatre workers (updated daily): I Lost My Theatre Gigs
“The Indie Theater Fund is launching this fundraising campaign to provide direct support and emergency relief to independent theaters and artists in response to the COVID-19 pandemic.” https://www.facebook.com/donate/509591526599992/509604039932074/
NYC Low-Income Artist/Freelancer Relief Fund: "We seek to provide support for low-income, BIPOC, trans/GNC/NB/Queer artists and freelancers whose livelihoods are being effected by this pandemic in NYC. Whether it's from cancelled gigs, lost jobs, or a lack of business due to coronavirus scares, we hope to orchestrate an egalitarian approach to crowdsourcing." [Note: their funding applications are currently closed as they make sure that they have enough resources to cover the 500 people who have already applied.] https://www.gofundme.com/f/nyc-lowincome-artistfreelancer-relief-fund
"The Philadelphia Performing Artists' Emergency Fund was created amid the COVID-19 outbreak to assist performing artists whose income has been impacted by show cancellations, slowing ticket sales, and/or low turnout during this pandemic." https://www.gofundme.com/f/philly-performance-artist-fund
"The Boston Artist Relief Fund will award grants of $500 and $1,000 to individual artists who live in Boston whose creative practices and incomes are being adversely impacted by Coronavirus Disease 2019 (COVID-19)." https://www.boston.gov/artistrelief
Boston Music Maker Relief Fund: "Small grants of up to $200 will be paid rapidly on a first come, first served basis to affected artists and groups. Please see grant guidelines below. Donations will be accepted from individuals and corporations in order to replenish the fund and continue making payments to eligible music makers in the queue. The Record Co. is covering all admin/processing costs so 100% of every donation goes directly to music makers in the community. Please consider donating using the form below or contact [email protected] to get involved.": https://www.therecordco.org/relief
Durham Artist Relief Fund: "Funds donated here go directly to artists and arts presenters in Durham who have been financially impacted by cancellations due to COVID-19, with priority given to to BIPOC artists, transgender & nonbinary artists, and disabled artists": https://www.northstardurham.com/artistrelief
Emergency Relief Fund for Artists During COVID-19 (Minnesota): https://www.givemn.org/story/Epf3ag
Opera San José Artists and Musicians Relief Fund: “This emergency cash reserve will allow us to provide support to the musicians, singers, carpenters, stitchers, designers and other hourly company members that make our productions possible and who will be deeply affected by COVID-19.”: https://operasj.secure.force.com/donate/?dfId=a0nf400000QZ7hKAAT
A pass the hat for individual SXSW workers: "Update 3/10: We have received over 400 submissions - thank you! We are working diligently to verify each submission and get them posted. As of today, the total amount of reported income lost is $2,108,835. Your stories are heartbreaking but we know them all too well. We appreciate you, we see you, and we love you, Austin. Hang in there." https://www.ilostmygig.com/
2020 ECCC Artists Alley: An unofficial compilation of Eccc2020 artist alley online shops. Browse the goods of artists who won't have the opportunity to sell directly to their anticipated customers: https://ecccartistalley.tumblr.com/
Artists Alley Online:  A directory for some of the artists who would have been at Emerald City Comic Con (March 12-15, 2020) had it not been moved due to the corona virus.  https://artistalleyonline.com/
Shoutout to the theaters who have suspended performances but are still paying their artists in the interim. These have been reported to include: Ars Nova (https://arsnovanyc.com/), Geffen Playhouse (https://www.geffenplayhouse.org/), WP Theater (https://wptheater.org/), Soho Rep (https://sohorep.org/), Playwrights Realm (https://www.playwrightsrealm.org/), New York Theatre Workshop (https://www.nytw.org/), Rattlestick Playwrights Theater (https://www.rattlestick.org/), the McCarter Theatre (https://www.mccarter.org/), Parity Productions (https://www.parityproductions.org/), and Second Stage Theater (https://2st.com/).  (sources: https://twitter.com/diepthought/status/1238194781437734912?s=19, direct email from Second Stage)
More who have been named are the Public Theater (https://publictheater.org/), Transport Group (http://transportgroup.org/), Vineyard Theatre (https://www.vineyardtheatre.org/), and Lincoln Center Theater (https://www.lct.org/). (source: https://twitter.com/westratenick/status/1238847988262453248)
Please consider giving those organizations (and any others who are doing similarly) your support if/when you're able to.
Resources for Impacted Arts/Entertainment/Events Workers
Freelancers & Community Resources 2020: Resources centered for artists and those impacted by gigs being canceled/postponed: https://docs.google.com/document/d/1xt1QZlGsyga_HrXagubV9O0rebV5dx4DuMOd2sWvWwc/edit
COVID-19 & Freelance Artist Resources: https://covid19freelanceartistresource.wordpress.com/
NYFA Emergency Resources: "Artists who experience personal hardship or who are impacted by a large-scale disaster, or who need funding for a last-minute opportunity can find critical resources in NYFA's Emergency Resources Directory.": https://www.nyfa.org/Content/Show/Emergency%20Resources
The Indie Theater Fund: "Rapid relief grants of up to $500 will be awarded to support our community, prioritizing the consortium of companies, venues, and individuals working in NYC independent theater (Off-Off-Broadway in theater houses of 99 seats or less), operating with budgets under $250,000. We will award grants on an on-going basis until our funds run out. Grants can be requested via a simple online application and will be reviewed on a first come first serve basis.”  https://forms.gle/pLm7bLhKQE8AbpDn6
Send your information to "I Lost My Theatre Gigs": https://ilostmytheatregigs.squarespace.com/
Philadelphia Performing Artists' Emergency Fund: Emergency Funds can be requested by any Cabaret, Drag, Burlesque, Theater, or performance artists facing a financial hardship caused by COVID-19. Performance artists who need aid can apply here: https://forms.gle/SwsMERPM1CTivFyc7
Boston Artist Relief Fund application: https://cityofbostonartsandculture.submittable.com/submit/af2153eb-2d87-4e9d-9ebc-5861eb135999/boston-artist-relief-fund
Boston Music Maker Relief Fund application: https://therecordco.typeform.com/to/w6wTkF
Durham Artist Relief Fund application: https://docs.google.com/forms/d/e/1FAIpQLSdEJKTP91h5e7MuUITHj96J6eKWeZjgVLZjLG4Wp-WMhyQ4mg/viewform
SXSW workers send your information to "I Lost My Gig" here: https://www.ilostmygig.com/
908 notes · View notes
onlineahmedali · 5 years
Link
Wordpress Forgot Admin Password - Part 23 - Best Way To Change Wp Pass And Email Just 1 side change
0 notes
Photo
Tumblr media
#HailCaesar #BirtherInChief #CorpMedia #Idiocracy #Oligarchs #MegaBanks vs #Union #Occupy #NoDAPL #BLM #SDF #DACA #MeToo #Humanity #DemExit
#WriteInBernie
The USPS is about to declare bankruptcy. It’s at the center of the longstanding plans for disaster recover and has been since the Cold War. It’s the only institution that could (for example) deliver covid meds to every home in America in one day.
https://pluralistic.net/2020/03/25/national-emergency-library/#going-postal
But Congress has decided not to bail out the postal service, despite Art 1, Sec 8 of the US Constitution: “To establish Post Offices and post Roads.”
Maybe it’s because without a USPS we couldn’t have a postal vote in 2020?
https://pluralistic.net/2020/03/27/just-asking-questions/#save-usps
The proximate cause of the post office’s bankruptcy is the pandemic, but that is merely the finishing blow. The USPS was murdered in 2006, when Congress passed the Postal Accountability and Enhancement Act.
https://www.nakedcapitalism.com/2020/04/will-the-united-states-post-office-become-a-victim-of-covid19.html
The Act gave the USPS a mere 10 years to “prefund its future health care benefit payments to retirees for the next 75 years.” That is, to set aside cash to pay medical bills for future employees who hadn’t been born yet.
https://www.govtrack.us/congress/bill.xpd?bill=h109-6407
The Act gave the USPS a mere 10 years to “prefund its future health care benefit payments to retirees for the next 75 years.” That is, to set aside cash to pay medical bills for future employees who hadn’t been born yet.
https://www.govtrack.us/congress/bill.xpd?bill=h109-6407
The USPS’s murder is straight out of the neoliberal playbook: “1 Defund, 2 claim crisis, 3 call for privatizatization, 4 profit!”
As Lambert Strether points out, it was a bipartisan act of murder, cosponored by the “centrist” Democrat Henry Waxman.
Killing the USPS looms large in the Trump admin’s (nonmetaphorical, actual) privatization playbook, “Delivering Government Solutions in the 21st Century Reform Plan and Reorganization Recommendations”:
https://www.whitehouse.gov/wp-content/uploads/2018/06/Government-Reform-and-Reorg-Plan.pdf
The proposals are for USPS to become a Wework clone or franchisee, but not to become a publicly owned bank - a common line of business for other nations’ postal services, natural based on the amounts of cash they handle.
The USPS is the nation’s second largest employer of veterans, with 630,000 employees. Trump is about to allow it to collapse so that UPS, Fedex and other private firms can skim off the most profitable parts of its business and leave rural Americans totally isolated.
The loss of the USPS would mean the loss of the last truly universal federal program in America and would unduly hammer the people whom Trump claims to love – veterans and rural voters.
https://twitter.com/lildipshit3/status/1248741868440940544 wilwheaton
I read a diary at Daily Kos which suggested that if half the households in America bought 2 sheets of Forever Stamps, for about 16 bucks, it would provide enough funding to keep the USPS alive.
How fucked up is this? We’re trying to save the fucking Postal Service, which is in the fucking CONSTITUTION, from Republican sabatoge.
There is no such thing as a moderate, or patriotic, Republican. They are anti-American Fascists. livebloggingmydescentintomadness
don’t miss the fact that this is coinciding exactly with the push to increase mail-in voting, which would seriously jeopardize Trump’s reelection. you can’t have mail-in ballots if there’s no postal service, right? Americans, please text USPS to 50409 and ResistBot will send a message to your senators and congressperson telling them to save the Post Office.
i did it yesterday and it couldn’t have been easier. my senators are both pieces of shit, but that doesn’t mean i’m not going to give them an earful about this. Source: mostlysignssomeportents
5 notes · View notes
sillyjunebug · 4 years
Text
192.168.1.1
You most likely know that your computer and your telephone have an IP address. A new version of the Web Protocol has also been created, known as IPv6. In contrast to its predecessor, IPv6 uses a 128-bit address, enabling for roughly three.4×1038 addresses, which is sufficient to assign a unique IPv6 address to each single atom on the surface of the Earth. Step four: Log in to the D-Hyperlink router with the administrator username and password. Go to this web site for more detailed directions and tools on finding your router's IP address.
To discover your router's IP quantity, look subsequent to "Default Gateway" (listed final). Step 1: Initial of all, connect the Netgear router with your Windows Pc and then open Browser and sort 192.168.1.1 > Enter. Examine regardless of whether the LAN wire is appropriately connected to your router and your pc or not. IP Address 192.168.1.1 belongs to a Private or Reserved variety, most of the IP Address specifics are not available.
Step 4: Go to Wireless Setting and modify settings that you want. Step four: Modify WiFi Password and Router Username. Step two: Sort 192.168.1.1 in browser > Enter. The router uses a diverse address than 192.168.1.1. Open a browser and kind that IP address to log into the router using the administrative ID and password. In case you can't access your router admin configuration web page by means of , let's find out which IP address your router is employing.
A much better option is to give the printer a private IP address so that only devices on the same network can reach it. Even so, the 192.168.0.1 IP address isn't usually utilized for printers but routers. All routers come with a internet interface that tends to make it possible to far more or less very easily modify various settings, and IP addresses such as 192.168.0.1 , 192.168.1.1 , or 192.168.. let you access it.
As we've just mentioned, it really is not possible to enter the 192.168.1. IP address unless you're connected to the exact same local network as the router to which the IP address is assigned. That should not be a dilemma if you are attempting to connect to your own property router. In some instances, it really is essential to connect straight through an Ethernet cable for security causes. I did the original setup, changed the admin admin password, designed a wifi network, it worked fine for a year (changins passwords after in a even though).
Following profitable login, you need to change the WiFi password and router username. Pick a strong password, a mixture of letters, symbols, and numbers. Here are some examples of how different router modes and switches would assign IP addresses to computer systems in a network. You will see the IP address next to default” (in the example under, the IP address is: 192.168.137.1). If you do not bear in mind your username and password, you can take benefit of default login specifics that are presented on the globe wide web. When it's worked, you ought to be asked for your password. Then you have to enter a username and password. Determine on a mix of letters and numbers to develop the password powerful.
Well, your Computer is showing a routable IP address as properly as default gateway so it would appear your router isn't carrying out considerably of anything. To access the RT-N12D1 settings, reconnect to the wireless network and use the updated IP address and port number. If you would like to make use of a specific router behind your ISP's router, you have two options: change your default IP address or keep the present configuration. Nonetheless, if you want to use a router behind your ISP's box, it is not necessary to have the router mode enabled on the existing configuration.
Sadly, most users don't even know how to log into router let alone how to adjust the default router password to one thing more safe. As told, the ip 192.168.1.11 is portion of a private class C network The range of this network is 192.168.. - 192.168.255.255. This make the quantity of attainable IP addresses 65,535. This range is typically employed on private networks simply because several routers are configured with 192.168.0.1 or 192.168.1.1 as their default address.
When you discover the correct address, you'll have to sign in making use of the router's managerial password. To seek out the IP Address, an person can adhere to any 1 of the next three methods. Public IP addresses are exclusive on the world wide web, but the personal ones aren't. Your router is the center of your network. Everything from the laptop you use to make on the internet purchases and handle your savings account to the baby monitor in your child's space connects to it. Cybercriminals are nicely aware of the central importance of routers, and they've created several sorts of malware to exploit weak router passwords.
As soon as you have accessed the admin panel of your router, you can modify numerous possibilities there, which includes PPOE, DNS, LAN, WAN, WLAN settings, IP QoS, Proxy, safety alternatives, network management, MAC, WPS , DHCP client or even your modem or wireless router's default IP address. Comment your situation if you are facing any. Thanks for reading this report on 192.168.0.1 IP address Login and Router Default Username and password. Also, Share us on Social Media.
Step 1: Plug D-Link router with your laptop or desktop with Ethernet cable. The number 192.168.0.1 is the default internet protocol address (or IP address) for all types of TP-hyperlink, D-Link and Netgear models. This private IPv4 network address can be changed at any time utilizing your network router's management console. In the case of other routers, you can variety ‘admin' as the default username and password. Often, you can also type ‘pass' or ‘password' in the password box.
Step three. Click the Network & Internet” choice. Step five. Select how you are connected to your router. If you are hardwired to your router choose Ethernet. If you are connected to your router via WiFi decide on Wi-Fi. Please post back right here with the outcomes of the test and the information on exactly exactly where your Computer network cable connects. But in most cases, the default IP Address for Modems and Routers is 192.168.0.1. Now you also need to have to Enter Default username and password in order to access its admin web page. The default username and password are diverse for a distinct manufacturer. Right here we are going to share all the possible Default Username and Password for 192.168.01 IP address.
Once you have carried out that, here's one thing else you can do. Disconnect your router from the world wide web and then guarantee you have your Pc plugged straight into a LAN port on the router. (NOTE: make note of exactly where each cable connects so you can place them back into the identical location after your accomplished. Make a diagram, take pic's with your smart phone etc.) As soon as you have the the two devices connected as I recommend, they will be isolated from almost everything else and this will aid to maintain troubleshooting as simple as possible.
192.1681.1 Router Admin Passwords and Login IP 192.1681.1 is an IP address which routers like Linksys and other network brands use as an access point or gateway.Firms set up router admin access in this address to enable network administrators to configure their routers and networks.Concretely one can manage Security Possibilities, Network Management, IP QoS, DNS, proxy, LAN, WAN, WLAN settings, DSL, ADSL, MAC, WPS block amongst others.
In this example the router's IP address is 192.168.1.1. Now, if you want to adjust Router Password, then go to advanced settings, and from there, choose admin password > Modify it > Save Settings, and it's accomplished. You must now see a login window with two input fields: one for the admin username and 1 for the admin password. Often due to improper connection or broken cable, you can't access the Router house web page. In that case, change the cable. If you forgot your router username and password, then you have to reset it.
1 note · View note
t-baba · 5 years
Photo
Tumblr media
How to Create Your Own AJAX WooCommerce Wishlist Plugin
In this tutorial we will create lightweight wishlist functionality for WooCommerce using AJAX, WordPress REST API, and SVG graphics. WooCommerce doesn’t come with wishlist functionality as standard, so you’ll always need to rely on an extension to do the work for you. Unless you build it yourself for complete control..
Wish Upon a Star
Wishlist functionality will allow users to mark certain products, adding them to a list for future reference. In some eCommerce stores (such as Amazon) multiple wishlists can be created, and these can be shared with others, which makes them ideal for birthdays or weddings. In our case, the WooCommerce wishlist we’re going to create will enable customers to easily revisit products they’re considering.
Our wishlist functionality will add a heart icon to the product thumbs, which when clicked will add the product to a wishlist in a table.
Click the heart icon to add a product to the wishlist
Take a look at the demo for a proper idea of how it works.
1. Create the Plugin Structure
Let’s start by building our plugin. Create a folder with the name “wishlist” and a PHP file with the same name. Add the following snippet to the PHP file:
/* Plugin Name: Woocommerce wishlist Plugin URI: https://www.enovathemes.com Description: Ajax wishlist for WooCommerce Author: Enovathemes Version: 1.0 Author URI: http://enovathemes.com */ if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly }
We won’t go into detail about the plugin creation process, but if you are new to plugin development I highly recommend this amazing new course by Rachel McCollin:
WordPress
Introduction to WordPress Plugin Development
Rachel McCollin
Add the Plugin Functions
Let’s sketch out our plan so we know what to build:
Add wishlist toggle to products in loop and single pages using WooCommerce hooks
Create wishlist table shortcode to hold the products added to the wishlist
Create wishlist custom option in the user profile
All the plugin code will go inside the init action for the plugin, as we first need to make sure that the WooCommerce plugin is active. So right after the plugin details add the following code:
add_action('init','plugin_init'); function plugin_init(){ if (class_exists("Woocommerce")) { // Code here } }
And now let’s enqueue our plugin scripts and styles.
Add the following code to the main plugin file:
function wishlist_plugin_scripts_styles(){ wp_enqueue_style( 'wishlist-style', plugins_url('/css/style.css', __FILE__ ), array(), '1.0.0' ); wp_enqueue_script( 'wishlist-main', plugins_url('/js/main.js', __FILE__ ), array('jquery'), '', true); wp_localize_script( 'main', 'opt', array( 'ajaxUrl' => admin_url('admin-ajax.php'), 'ajaxPost' => admin_url('admin-post.php'), 'restUrl' => rest_url('wp/v2/product'), 'shopName' => sanitize_title_with_dashes(sanitize_title_with_dashes(get_bloginfo('name'))), 'inWishlist' => esc_html__("Already in wishlist","text-domain"), 'removeWishlist' => esc_html__("Remove from wishlist","text-domain"), 'buttonText' => esc_html__("Details","text-domain"), 'error' => esc_html__("Something went wrong, could not add to wishlist","text-domain"), 'noWishlist' => esc_html__("No wishlist found","text-domain"), ) ); } add_action( 'wp_enqueue_scripts', 'wishlist_plugin_scripts_styles' );
Here we enqueue the main style.css file and the main.js file for the plugin, also we pass some parameters to the main.js file to work with:
ajaxUrl – required to fetch some data from WordPress, like current User ID
ajaxPost – required to update user wishlist
restUrl – required to list the wishlist items in the wishlist table
shopName – required to add wishlist items to the session storage for non-registered or non-logged-in users
And some strings instead of hardcoding them into the js file, in case they need to be translatable.
So for now create a css, and js folder and put the corresponding files inside those folders: style.css in the css folder and main.js in the js folder.
2. Hook the Wishlist Toggle
Right inside the init action add the following code:
// Add wishlist to product add_action('woocommerce_before_shop_loop_item_title','wishlist_toggle',15); add_action('woocommerce_single_product_summary','wishlist_toggle',25); function wishlist_toggle(){ global $product; echo '<span class="wishlist-title">'.esc_attr__("Add to wishlist","text-domain").'</span><a class="wishlist-toggle" data-product="'.esc_attr($product->get_id()).'" href="#" title="'.esc_attr__("Add to wishlist","text-domain").'">'.file_get_contents(plugins_url( 'images/icon.svg', __FILE__ )).'</a>'; }
Here we add a wishlist toggle to each product in the loop and to each single product layout, using the woocommerce_before_shop_loop_item_title and woocommerce_single_product_summary hooks.
Here I want to point out the data-product attribute that contains the product ID–this is required to power the wishlist functionality. And also take a closer look at the SVG icon–this is required to power the animation. 
3. Add SVG Icons
Now create an images folder in the plugin folder and put the following icon.svg in it:
<svg viewBox="0 0 471.701 471.701"> <path class="heart" d="M433.601,67.001c-24.7-24.7-57.4-38.2-92.3-38.2s-67.7,13.6-92.4,38.3l-12.9,12.9l-13.1-13.1 c-24.7-24.7-57.6-38.4-92.5-38.4c-34.8,0-67.6,13.6-92.2,38.2c-24.7,24.7-38.3,57.5-38.2,92.4c0,34.9,13.7,67.6,38.4,92.3 l187.8,187.8c2.6,2.6,6.1,4,9.5,4c3.4,0,6.9-1.3,9.5-3.9l188.2-187.5c24.7-24.7,38.3-57.5,38.3-92.4 C471.801,124.501,458.301,91.701,433.601,67.001z M414.401,232.701l-178.7,178l-178.3-178.3c-19.6-19.6-30.4-45.6-30.4-73.3 s10.7-53.7,30.3-73.2c19.5-19.5,45.5-30.3,73.1-30.3c27.7,0,53.8,10.8,73.4,30.4l22.6,22.6c5.3,5.3,13.8,5.3,19.1,0l22.4-22.4 c19.6-19.6,45.7-30.4,73.3-30.4c27.6,0,53.6,10.8,73.2,30.3c19.6,19.6,30.3,45.6,30.3,73.3 C444.801,187.101,434.001,213.101,414.401,232.701z"/> <g class="loading"> <path d="M409.6,0c-9.426,0-17.067,7.641-17.067,17.067v62.344C304.667-5.656,164.478-3.386,79.411,84.479 c-40.09,41.409-62.455,96.818-62.344,154.454c0,9.426,7.641,17.067,17.067,17.067S51.2,248.359,51.2,238.933 c0.021-103.682,84.088-187.717,187.771-187.696c52.657,0.01,102.888,22.135,138.442,60.976l-75.605,25.207 c-8.954,2.979-13.799,12.652-10.82,21.606s12.652,13.799,21.606,10.82l102.4-34.133c6.99-2.328,11.697-8.88,11.674-16.247v-102.4 C426.667,7.641,419.026,0,409.6,0z"/> <path d="M443.733,221.867c-9.426,0-17.067,7.641-17.067,17.067c-0.021,103.682-84.088,187.717-187.771,187.696 c-52.657-0.01-102.888-22.135-138.442-60.976l75.605-25.207c8.954-2.979,13.799-12.652,10.82-21.606 c-2.979-8.954-12.652-13.799-21.606-10.82l-102.4,34.133c-6.99,2.328-11.697,8.88-11.674,16.247v102.4 c0,9.426,7.641,17.067,17.067,17.067s17.067-7.641,17.067-17.067v-62.345c87.866,85.067,228.056,82.798,313.122-5.068 c40.09-41.409,62.455-96.818,62.344-154.454C460.8,229.508,453.159,221.867,443.733,221.867z"/> </g> <g class="check"> <path d="M238.933,0C106.974,0,0,106.974,0,238.933s106.974,238.933,238.933,238.933s238.933-106.974,238.933-238.933 C477.726,107.033,370.834,0.141,238.933,0z M238.933,443.733c-113.108,0-204.8-91.692-204.8-204.8s91.692-204.8,204.8-204.8 s204.8,91.692,204.8,204.8C443.611,351.991,351.991,443.611,238.933,443.733z"/> <path d="M370.046,141.534c-6.614-6.388-17.099-6.388-23.712,0v0L187.733,300.134l-56.201-56.201 c-6.548-6.78-17.353-6.967-24.132-0.419c-6.78,6.548-6.967,17.353-0.419,24.132c0.137,0.142,0.277,0.282,0.419,0.419 l68.267,68.267c6.664,6.663,17.468,6.663,24.132,0l170.667-170.667C377.014,158.886,376.826,148.082,370.046,141.534z"/> </g> </svg>
If you are new to working with SVGs I highly recommend you read these amazing tutorials on the subject:
SVG
How to Hand Code SVG
Kezz Bracey
SVG
SVG Viewport and viewBox (For Complete Beginners)
Kezz Bracey
Our SVG animation has 3 states:
Default: the heart path
Process: loading group (g tag)
End: check group (g tag)
If you now go to your shop page you will see the unstyled SVG icons piled on top of each other:
Let’s add some styling to fix this mess! Open the style.css file and paste the following code:
.wishlist-toggle { display: block; position: absolute; top: 16px; left: 16px; z-index: 5; width: 24px; height: 24px; outline: none; border:none; } .wishlist-title { display: none; } .entry-summary .wishlist-toggle { position: relative; top: 0; left: 0; display: inline-block; vertical-align: middle; margin-bottom: 8px; } .entry-summary .wishlist-title { display: inline-block; vertical-align: middle; margin-right: 8px; margin-bottom: 8px; } .wishlist-toggle:focus { outline: none; border:none; } .wishlist-toggle svg { fill:#bdbdbd; transition: all 200ms ease-out; } .wishlist-toggle:hover svg, .wishlist-toggle.active svg { fill:#000000; } .wishlist-toggle svg .loading, .wishlist-toggle svg .check { opacity: 0; } .wishlist-toggle.active svg .check { opacity: 1; } .wishlist-toggle.active svg .heart { opacity: 0; } .wishlist-toggle.loading svg .loading, .wishlist-table.loading:before { animation:loading 500ms 0ms infinite normal linear; transform-origin: center; opacity: 1; } .wishlist-toggle.loading svg .heart { opacity:0; } @keyframes loading { from {transform: rotate(0deg);} to {transform: rotate(360deg);} }
The logic here is as follows: 
Initially we show the heart path of our SVG.
When the user clicks on it we will hide the heart path and show the loading path.
Once the loading finishes we will show the checkmark indicating that the product was successfully added to the wishlist.
We will toggle the loading state via JavaScript later; the loading animation is a simple transform rotate. So for now if you refresh the page (don’t forget to clear the browser cache as sometimes old styles are cached) you will see a nice heart icon with each product. 
This toggle currently does nothing, so we’ll sort that out. But for now let’s keep with our plan.
4. Create Wishlist Table Shortcode
Add the following code in the init plugin action:
// Wishlist table shortcode add_shortcode('wishlist', 'wishlist'); function wishlist( $atts, $content = null ) { extract(shortcode_atts(array(), $atts)); return '<table class="wishlist-table loading"> <tr> <th><!-- Left for image --></th> <th>'.esc_html__("Name","text-domain").'</th> <th>'.esc_html__("Price","text-domain").'</th> <th>'.esc_html__("Stock","text-domain").'</th> <th><!-- Left for button --></th> </tr> </table>'; }
This is a very simple shortcode that you can add to any page, and the wishlist items will appear inside it. I won’t describe the shortcode creation process, but if you are new to this, I highly recommend reading this amazing tutorial:
Plugins
Getting Started With WordPress Shortcodes
Rohan Mehta
Make a Wishlist Page
Now from inside the WP admin create a page called “Wishlist” and put the [wishlist] shortcode inside it. Now if you go to the wishlist page you will see an empty table.
Did you notice the loading class on the table? We will remove the loading class with JavaScript later, once the wishlist items are ready to be appended to the table. But for now open the style.css and add the following code:
.wishlist-table { width:100%; position: relative; } .wishlist-table.loading:after { display: block; width: 100%; height: 100%; position: absolute; top: 0; left: 0; content: ""; background: #ffffff; opacity: 0.5; z-index: 5; } .wishlist-table.loading:before { display: block; width: 24px; height: 24px; position: absolute; top: 50%; left: 50%; margin-top:-12px; margin-left:-12px; content: ""; background-image: url('../images/loading.svg'); background-repeat: no-repeat; background-size: 100%; z-index: 6; } .wishlist-table td { position: relative; } .wishlist-table a.details { padding:4px 16px; background: #000000; color: #ffffff; text-align: center; border:none !important } .wishlist-table a.wishlist-remove { display: block; width: 24px; height: 24px; position: absolute; top: 50%; left: 50%; margin-top:-12px; margin-left:-12px; background-image: url('../images/remove.svg'); background-repeat: no-repeat; background-size: 100%; z-index: 6; border:none; opacity:0; } .wishlist-table td:hover > a.wishlist-remove { opacity:1; }
Add the loading.svg image to the images folder:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 471.701 471.701"> <path d="M409.6,0c-9.426,0-17.067,7.641-17.067,17.067v62.344C304.667-5.656,164.478-3.386,79.411,84.479 c-40.09,41.409-62.455,96.818-62.344,154.454c0,9.426,7.641,17.067,17.067,17.067S51.2,248.359,51.2,238.933 c0.021-103.682,84.088-187.717,187.771-187.696c52.657,0.01,102.888,22.135,138.442,60.976l-75.605,25.207 c-8.954,2.979-13.799,12.652-10.82,21.606s12.652,13.799,21.606,10.82l102.4-34.133c6.99-2.328,11.697-8.88,11.674-16.247v-102.4 C426.667,7.641,419.026,0,409.6,0z"/> <path d="M443.733,221.867c-9.426,0-17.067,7.641-17.067,17.067c-0.021,103.682-84.088,187.717-187.771,187.696 c-52.657-0.01-102.888-22.135-138.442-60.976l75.605-25.207c8.954-2.979,13.799-12.652,10.82-21.606 c-2.979-8.954-12.652-13.799-21.606-10.82l-102.4,34.133c-6.99,2.328-11.697,8.88-11.674,16.247v102.4 c0,9.426,7.641,17.067,17.067,17.067s17.067-7.641,17.067-17.067v-62.345c87.866,85.067,228.056,82.798,313.122-5.068 c40.09-41.409,62.455-96.818,62.344-154.454C460.8,229.508,453.159,221.867,443.733,221.867z"/> </svg>
This is the same loading SVG separated from the main icon.svg. We could use SVG sprites, but I decided to stick with a separate loading SVG.
Now, if you go to the wishlist page and refresh it you will see an empty table with loading on it. Nice, let’s move further.
5. Wishlist Custom Option in the User Profile
Our wishlist functionality will work both for logged-in users and guest users. With logged-in users we’ll store the wishlist information in the user’s metadata, and with guest users we’ll store the wishlist in the session storage. 
You can also store the guest users’ wishlist in local storage, the difference being that session storage is destroyed when the user closes the tab or browser, and local storage is destroyed when the browser cache is cleared. It is up to you which option you use for guest users.
Now add the following code to the init action:
// Wishlist option in the user profile add_action( 'show_user_profile', 'wishlist_user_profile_field' ); add_action( 'edit_user_profile', 'wishlist_user_profile_field' ); function wishlist_user_profile_field( $user ) { ?> <table class="form-table wishlist-data"> <tr> <th><?php echo esc_attr__("Wishlist","text-domain"); ?></th> <td> <input type="text" name="wishlist" id="wishlist" value="<?php echo esc_attr( get_the_author_meta( 'wishlist', $user->ID ) ); ?>" class="regular-text" /> </td> </tr> </table> <?php } add_action( 'personal_options_update', 'save_wishlist_user_profile_field' ); add_action( 'edit_user_profile_update', 'save_wishlist_user_profile_field' ); function save_wishlist_user_profile_field( $user_id ) { if ( !current_user_can( 'edit_user', $user_id ) ) { return false; } update_user_meta( $user_id, 'wishlist', $_POST['wishlist'] ); }
Again, in order to remain within the scope of this tutorial, I won’t explain how to work with user metadata. If you are new to this I highly recommend reading this amazing tutorial:
WordPress
How to Work With WordPress User Metadata
Tom McFarlin
All we do here is create a text field input that will hold the wishlist items comma-separated IDs. With show_user_profile and edit_user_profile actions we add the structure of the input field, and with personal_options_update and edit_user_profile_update actions we power the save functionality. 
So once the wishlist is updated it will save to the database. I you go to your profile page you will see a new text field added to it. Add whatever value you want and hit save to test if the update functionality works. With admin CSS you can hide this field if you don’t want users to see it. I will leave it as is.
6. Turn it On!
Now we are ready to power everything up!
Open the main.js file and put the following code in it:
(function($){ "use strict"; })(jQuery);
All our code will go inside this function.
Now let’s gather the required data and create some variables:
var shopName = opt.shopName+'-wishlist', inWishlist = opt.inWishlist, restUrl = opt.restUrl, wishlist = new Array, ls = sessionStorage.getItem(shopName), loggedIn = ($('body').hasClass('logged-in')) ? true : false, userData = '';
As you might remember when we enqueued our main.js script we passed some parameters to it. Here, with JavaScript, we can collect these parameters.
Next, we will create an empty wishlist array that will contains wishlist items. We will need the session storage data with our shop name (the ls variable stands for local storage), and we will need to know if the user is guest or logged-in.
Let me explain the logic here: whenever the user visits the shop page we will need to know if he or she is logged-in or is a guest-user. If the user is logged-in we will need to check if he or she has wishlist items, and if so highlight these items. If not we need to see if there are any items in the session/local storage and highlight those. 
Why this is done like this? Imagine, if the user first visits the website as a guest, adds items to the wishlist, and then decides to login. If the user does not have items registered in the profile wishlist, we will need to show the ones that he or she added before login, that are stored in the session/local storage.
So let’s do that step by step:
If User is Logged-in
Fetch current user data with AJAX
If success update the wishlist
Highlight the wishlist items
Remove the session/local storage
If fail show error message in the console for the developer
if(loggedIn) { // Fetch current user data $.ajax({ type: 'POST', url: opt.ajaxUrl, data: { 'action' : 'fetch_user_data', 'dataType': 'json' }, success:function(data) { userData = JSON.parse(data); if (typeof(userData['wishlist']) != 'undefined' && userData['wishlist'] != null && userData['wishlist'] != "") { var userWishlist = userData['wishlist']; userWishlist = userWishlist.split(','); if (wishlist.length) { wishlist = wishlist.concat(userWishlist); $.ajax({ type: 'POST', url:opt.ajaxPost, data:{ action:'user_wishlist_update', user_id :userData['user_id'], wishlist :wishlist.join(','), } }); } else { wishlist = userWishlist; } wishlist = wishlist.unique(); highlightWishlist(wishlist,inWishlist); sessionStorage.removeItem(shopName); } else { if (typeof(ls) != 'undefined' && ls != null) { ls = ls.split(','); ls = ls.unique(); wishlist = ls; } $.ajax({ type: 'POST', url:opt.ajaxPost, data:{ action:'user_wishlist_update', user_id :userData['user_id'], wishlist :wishlist.join(','), } }) .done(function(response) { highlightWishlist(wishlist,inWishlist); sessionStorage.removeItem(shopName); }); } }, error: function(){ console.log('No user data returned'); } }); }
If User is Guest
Fetch wishlist from the session/local storage
else { if (typeof(ls) != 'undefined' && ls != null) { ls = ls.split(','); ls = ls.unique(); wishlist = ls; } }
As you may have noticed here we have double-AJAX and some helper functions. So first let’s create the actions of the AJAX requests, and after that I will explain our helper functions. I won’t describe in detail the AJAX functionality in WordPress, but if you are new to AJAX and WordPress, I highly recommend reading this amazing tutorial on it:
Plugins
A Primer on Ajax in the WordPress Frontend: Understanding the Process
Tom McFarlin
Our first AJAX request gets the user id and the user wishlist data from WordPress. This is done with a custom AJAX action added to the plugin code file:
// Get current user data function fetch_user_data() { if (is_user_logged_in()){ $current_user = wp_get_current_user(); $current_user_wishlist = get_user_meta( $current_user->ID, 'wishlist',true); echo json_encode(array('user_id' => $current_user->ID,'wishlist' => $current_user_wishlist)); } die(); } add_action( 'wp_ajax_fetch_user_data', 'fetch_user_data' ); add_action( 'wp_ajax_nopriv_fetch_user_data', 'fetch_user_data' );
The most important part here is the action name (fetch_user_data)–make sure it is the same for AJAX and for functions wp_ajax_fetch_user_data and wp_ajax_nopriv_fetch_user_data. Here we’re preparing JSON formatted data with user ID and user wishlist data.
Our next AJAX request updates the user wishlist if there were already wishlist items from session/local storage. Take a close look at the url option–see it is different.
The logic is the same as for the first action–the difference is that here we don’t return or echo any data, but we update the wishlist option for the current user.
function update_wishlist_ajax(){ if (isset($_POST["user_id"]) && !empty($_POST["user_id"])) { $user_id = $_POST["user_id"]; $user_obj = get_user_by('id', $user_id); if (!is_wp_error($user_obj) && is_object($user_obj)) { update_user_meta( $user_id, 'wishlist', $_POST["wishlist"]); } } die(); } add_action('admin_post_nopriv_user_wishlist_update', 'update_wishlist_ajax'); add_action('admin_post_user_wishlist_update', 'update_wishlist_ajax');
And if our user is a guest we will need to check if there are any wishlist details in the session/local storage.
Helper Functions
Before we move to the events part I want to explain our helper functions
Array.prototype.unique = function() { return this.filter(function (value, index, self) { return self.indexOf(value) === index; }); } function isInArray(value, array) {return array.indexOf(value) > -1;} function onWishlistComplete(target, title){ setTimeout(function(){ target .removeClass('loading') .addClass('active') .attr('title',title); },800); } function highlightWishlist(wishlist,title){ $('.wishlist-toggle').each(function(){ var $this = $(this); var currentProduct = $this.data('product'); currentProduct = currentProduct.toString(); if (isInArray(currentProduct,wishlist)) { $this.addClass('active').attr('title',title); } }); }
The first helper function makes the array unique, by removing duplicates, the second one checks if the given value is present in the given array. The next function executes when an item is added to the wishlist and the last one shows items that are in the wishlist.
Add Toggle
Now let’s add a click event to the wishlist toggle to power the actual functionality. On each toggle click event the animation is triggered and if the user is logged-in the wishlist update action fires with AJAX. If the user is a guest the item is added to the session/local storage. 
Now if you go to the shop page, refresh the browser, and click on any wishlist toggle you will see it is working!
$('.wishlist-toggle').each(function(){ var $this = $(this); var currentProduct = $this.data('product'); currentProduct = currentProduct.toString(); if (!loggedIn && isInArray(currentProduct,wishlist)) { $this.addClass('active').attr('title',inWishlist); } $(this).on('click',function(e){ e.preventDefault(); if (!$this.hasClass('active') && !$this.hasClass('loading')) { $this.addClass('loading'); wishlist.push(currentProduct); wishlist = wishlist.unique(); if (loggedIn) { // get user ID if (userData['user_id']) { $.ajax({ type: 'POST', url:opt.ajaxPost, data:{ action:'user_wishlist_update', user_id :userData['user_id'], wishlist :wishlist.join(','), } }) .done(function(response) { onWishlistComplete($this, inWishlist); }) .fail(function(data) { alert(opt.error); }); } } else { sessionStorage.setItem(shopName, wishlist.toString()); onWishlistComplete($this, inWishlist); } } }); });
7. List Items in Wishlist Table
Now it is time to list our wishlist items in the wishlist table we created earlier.
Add the following code into main.js at the very bottom of our wrapper function:
setTimeout(function(){ if (wishlist.length) { restUrl += '?include='+wishlist.join(','); restUrl += '&per_page='+wishlist.length; $.ajax({ dataType: 'json', url:restUrl }) .done(function(response){ $('.wishlist-table').each(function(){ var $this = $(this); $.each(response,function(index,object){ $this.append('<tr data-product="'+object.id+'"><td><a class="wishlist-remove" href="#" title="'+opt.removeWishlist+'"></a>'+object.image+'</td><td>'+object.title["rendered"]+'</td><td>'+object.price+'</td><td>'+object.stock+'</td><td><a class="details" href="'+object.link+'">'+opt.buttonText+'</a></td></tr>'); }); }); }) .fail(function(response){ alert(opt.noWishlist); }) .always(function(response){ $('.wishlist-table').each(function(){ $(this).removeClass('loading'); }); }); } else { $('.wishlist-table').each(function(){ $(this).removeClass('loading'); }); } },1000);
Here we are using the WordPress REST API to get the products by ID in the wishlist array. 
For each of the products we get we are adding a table row with the required data to display. We need the product image, title, stock status, button and price. 
Here we have two options for the REST API: 
using the WordPress REST API 
using the WooCommerce REST API. 
The difference here is that product data is already present in the Woocommerce REST API, but an API key is required. With the default WordPress REST API product data is absent by default, but can be added, and no API key is required. For such a simple task as a wishlist I don’t think that an API key is needed, so we will do it by extending the default WordPress REST API to return our product price, image code and the stock level.
Go to the main plugin file and at the very bottom add the following code:
// Extend REST API function rest_register_fields(){ register_rest_field('product', 'price', array( 'get_callback' => 'rest_price', 'update_callback' => null, 'schema' => null ) ); register_rest_field('product', 'stock', array( 'get_callback' => 'rest_stock', 'update_callback' => null, 'schema' => null ) ); register_rest_field('product', 'image', array( 'get_callback' => 'rest_img', 'update_callback' => null, 'schema' => null ) ); } add_action('rest_api_init','rest_register_fields'); function rest_price($object,$field_name,$request){ global $product; $id = $product->get_id(); if ($id == $object['id']) { return $product->get_price(); } } function rest_stock($object,$field_name,$request){ global $product; $id = $product->get_id(); if ($id == $object['id']) { return $product->get_stock_status(); } } function rest_img($object,$field_name,$request){ global $product; $id = $product->get_id(); if ($id == $object['id']) { return $product->get_image(); } } function maximum_api_filter($query_params) { $query_params['per_page']["maximum"]=100; return $query_params; } add_filter('rest_product_collection_params', 'maximum_api_filter');
All this does is create new fields for REST API and extends the maximum items limit per request. Again, if you are new to this subject I highly recommend reading this series.
For now, if you go to your wishlist table and refresh the page you will see the list of items that are added to your wishlist. 
8. Removing Items From Wishlist
We are almost done; only the remove functionality remains. So let’s create that! Add the following code at the very bottom of the wrapper function in the main.js file
$(document).on('click', '.wishlist-remove', function(){ var $this = $(this); $this.closest('table').addClass('loading'); wishlist = []; $this.closest('table').find('tr').each(function(){ if ($(this).data('product') != $this.closest('tr').data('product')) { wishlist.push($(this).data('product')); if (loggedIn) { // get user ID if (userData['user_id']) { $.ajax({ type: 'POST', url:opt.ajaxPost, data:{ action:'user_wishlist_update', user_id :userData['user_id'], wishlist :wishlist.join(','), } }) .done(function(response) { $this.closest('table').removeClass('loading'); $this.closest('tr').remove(); }) .fail(function(data) { alert(opt.error); }); } } else { sessionStorage.setItem(shopName, wishlist.toString()); setTimeout(function(){ $this.closest('table').removeClass('loading'); $this.closest('tr').remove(); },500); } } }); });
Once the remove icon is clicked (make sure you have a remove.svg in the images folder, you can use whatever icon you want), we need to check if the user is logged-in. If so, we then remove the item ID from the wishlist using AJAX with the user_wishlist_update action. If the user is a guest we need to remove the item ID from the session/local storage.
Now go to your wishlist and refresh the page. Once you click on the remove icon your item will be removed from the wishlist.
Conclusion
That was quite a project! A simple, but comprehensive wishlist feature for your WooCommerce stores. You are free to use this plugin in any project; you can extend, modify it and make suggestions. I hope you liked it. Here is the link to the source files on GitHub. And here is the demo.
Learn More WooCommerce Theme Development
At Tuts+ we have a great collection of tutorials and courses to learn WooCommerce development. Check out these four great courses to get started!
WooCommerce
Up and Running With WooCommerce
Rachel McCollin
WordPress
Developing a WooCommerce Theme
Rachel McCollin
WordPress
Go Further With WooCommerce Themes
Rachel McCollin
WordPress
How to Make Your Theme WooCommerce Compatible
Rachel McCollin
by Karen Pogosyan via Envato Tuts+ Code https://ift.tt/2WTWfiG
1 note · View note
forestdo98-blog · 5 years
Text
Hello guys
My name is Forest Do - an enthusiastic creative and CEO of eyeskady.com. I experienced my childhood in California, USA and I was interested in unique items when I was a little kid. My father used to give me some special items with impressive design on my birthday. From then, uniquely - designed things turned into my passion and I start opening a bussiness to selling special mugs, T-shirt as well as hoodie - eyeskady.com. In addition to that, I’m a dad of one kids as well as a highly responsible husband. Our family usually go to the fair or exhibition and enjoy art as well as let our children to draw whatever they want. That’s why I love unique items as we can associate and share the fascinating moment together. I’m very proud of my son – Joe as he also adores designing his clothes by drawing on it. My wife – Demi always support my work – a freelance creative and a fashion designer at part-time. Address: 113 Doi Can, Ba Dinh, Hanoi, Vietnam 100000 Phone: +84 978696652 Website: https://eyeskady.com Email: [email protected] Social: https://twitter.com/ForestDo98
https://medium.com/@forestdo98 https://www.reddit.com/user/forestdo98 https://www.plurk.com/forestdo98 http://www.tagged.com/forestdo98 https://getpocket.com/@forestdo98 https://soundcloud.com/forestdo98 https://gab.com/Forestdo98 https://www.instapaper.com/p/forestdo98 https://list.ly/forestdo98 https://www.followly.net/forestdo98 https://philpeople.org/profiles/forest-do http://www.hi5.com/forestdo98 https://www.bibsonomy.org/user/forestdo98 https://news.ycombinator.com/user?id=Forestdo98 https://www.meetup.com/members/287894344/ https://www.flickr.com/people/183630209@N02/ https://www.facebook.com/forestdo98 https://twitter.com/ForestDo98 https://forestdo98.tumblr.com/ https://profiles.wordpress.org/forestdo98/ https://www.instagram.com/forestdo98/ http://forum.modulo.ro/jforum/user/editDone/11252.page https://www.blogger.com/profile/00167556685887287123 https://angel.co/forestdo98 https://disqus.com/by/forestdo98/ https://vi.gravatar.com/ https://www.linkedin.com/in/forest-do-b19679190/ https://www.skillshare.com/profile/Forest-Do/4116534 https://www.goodreads.com/forestdo98 https://account.articulate.com/ https://vk.com/id559397642 https://www.ok.ru/forestdo98 https://www.strava.com/athletes/forestdo98 https://dribbble.com/Forestdo98 https://www.tripadvisor.com.vn/Profile/Forestdo https://www.ted.com/profiles/14676718 https://www.behance.net/forestdo98/ https://issuu.com/forestdo98 https://www.youtube.com/channel/UCEkZfQVIb5_eN3ah6Mdj9_A?view_as=subscriber https://www.kickstarter.com/profile/459881150 https://foursquare.com/user/553871616 https://forestdo98.livejournal.com/profile https://forestdo98.weebly.com/ https://www.houzz.com/user/forestdo98 https://www.khanacademy.org/profile/forestdo98/ https://www.wix.com/account/account-settings?referralAdditionalInfo=Dashboard https://dash.e.jimdo.com/profile https://www.reverbnation.com/forestdo98 https://pixabay.com/users/forestdo98-13358570/ https://www.patreon.com/user/creators?ru=%2Fhome about.me/forestdo98 https://www.lonelyplanet.com/profile/forestdo98 https://www.quora.com/profile/Forest-Do http://forestdo98.over-blog.com/ https://boards.fool.com/profile/forestdo98/info.aspx https://trello.com/forestdo98 https://www.periscope.tv/forestdo98 http://stationfm.ning.com/profile/Forestdo98 https://www.sbnation.com/users/Forestdo98 https://www.deviantart.com/forestdo98 https://www.codecademy.com/profiles/forestdo98 https://www.blurb.com/user/Forestdo98 https://hubpages.com/@forestdo98 https://www.smashwords.com/profile/view/Forestdo98 https://genius.com/Forestdo98 https://speakerdeck.com/forestdo98 https://500px.com/forestdo98 https://weheartit.com/forestdo98 https://armchairgm.fandom.com/wiki/User:Forestdo98 https://www.pearltrees.com/forestdo98 https://www.spreaker.com/user/forestdo98 http://www.dronestagr.am/author/forestdo98/ https://profile.cheezburger.com/forestdo98/ https://musicbrainz.org/user/Forestdo98 https://www.colourlovers.com/lover/Forestdo98 https://forestdo98.newgrounds.com/ https://www.wattpad.com/user/forestdo98 http://www.maprecord.com/forum/member.php?action=profile&uid=29707 https://ask.fm/Forestdo98 https://www.crunchyroll.com/user/Forestdo98 https://www.crowdfunder.co.uk/user/forest-do/profile https://n4g.com/user/score/forestdo98 https://www.travellerspoint.com/users/Forestdo98/ https://independent.academia.edu/DoForest https://www.intensedebate.com/profiles/forestdo98 http://www.folkd.com/user/forestdo98 https://wanelo.co/forestdo98 https://www.adsoftheworld.com/user/forestdo98 https://www.f6s.com/forestdo https://ello.co/forestdo98 https://www.ranker.com/profile-of/forestdo98 https://www.etsy.com/people/5irnnhug?ref=hdr_user_menu https://www.fitbit.com/user/7QBZ39 http://www.authorstream.com/Forestdo98/ https://gfycat.com/@Forestdo98 https://www.heraldextra.com/users/profile/forestdo98/ https://www.scoop.it/u/forest-do https://zippyshare.com/Forestdo98 https://pastebin.com/u/Forestdo98 https://www.tradingview.com/u/forestdo98/ https://www.designspiration.net/forestdo98/saves/ https://www.gaiaonline.com/profiles/forestdo98/43888911/ https://deskgram.net/forestdo98 https://pitaname.com/forestdo98 https://www.brusheezy.com/members/forestdo98 https://works.bepress.com/forest-do/ https://tinychat.com/room/forestdo98 https://untappd.com/user/forestdo98 http://www.singsnap.com/karaoke/member/forestdo98 https://www.trover.com/u/forestdo98 https://maps.roadtrippers.com/people/Forestdo98 https://www.artfire.com/ext/people/forestdo98 https://letterboxd.com/Forestdo98/ https://www.last.fm/user/Forestdo98 https://allevents.in/org/forest-do/16405114 https://bucketlist.org/list/forestdo98/ https://www.statsguru.net/u/forestdo98 https://www.care2.com/my/petitionsite https://www.buzzsprout.com/admin/users/479587/edit https://fancy.com/forestdo98 https://sumally.com/forestdo98 https://photopeach.com/user/forestdo98 https://www.edocr.com/user/forestdo98 https://www.hulkshare.com/forestdo98 https://blip.fm/forestdo98 https://www.slideserve.com/account/profile.php https://tapas.io/forestdo98 https://www.allnumis.com/user/profile/Forestdo98 https://trakt.tv/users/forestdo98 https://sketchfab.com/forestdo98 https://degreed.com/forestdo98/index/1#/pathways https://www.myballard.com/wp-admin/profile.php https://my.desktopnexus.com/Forestdo98/ https://www.thingiverse.com/Forestdo98/about https://www.chairish.com/shop/forestdo98 https://www.concertwindow.com/221069-forestdo98 http://www.testadsl.net/forum/profile.php?id=32915 https://www.trepup.com/forestdo98 http://www.fixya.com/users/forestdo98?up=1 http://myfolio.com/forestdo98 http://www.fotobabble.com/m/eUw1VHZ0WkNLM1k9 https://www.blackplanet.com/Forestdo98 http://guildwork.com/users/forestdo98 https://enetget.com/forestdo98 https://www.wishlistr.com/profile/ https://dashburst.com/forestdo98 https://yelloyello.com/places/Forestdo98 https://hub.docker.com/u/forestdo98 https://twinoid.com/user/9869468 https://www.webstagram.biz/forestdo98 http://whazzup-u.com/profile/ForestDo https://account.xiaomi.com/pass/auth/profile/home?cUserId=_d_wjNbToYhrUM9-zPylLTuev_g&userId=6235426892 https://www.fiverr.com/forestdo98?public_mode=true https://coub.com/forestdo98 https://accounts.radionomy.com/en/profile https://www.burdastyle.com/profiles/forestdo98 https://www.slideshare.net/ForestDo https://www.picbear.org/user/forestdo98 https://myspace.com/forestdo98/ http://qooh.me/forestdo98 https://www.webstagram.biz/forestdo98 https://forum.elster.de/anwenderforum/member.php?614380-Forestdo98 https://codepen.io/Forestdo98 https://sumally.com/forestdo98 https://www.viki.com/users/forestdo98/about https://followus.com/Forestdo98 http://digg.com/u/forestdo98 https://www.pinterest.com/forestdo98/ https://forums.tccoa.com/members/63673-lam-do.html http://www.4mark.net/profile.aspx https://theta360.com/users/343964 https://forums.civfanatics.com/members/forestdo.321046/ https://account.ubisoft.com/en-GB/account-information https://archive.org/details/69747389402718827039525903394770976505856n https://wiki.ironrealms.com/Main/ForestDo https://www.producthunt.com/@lam_do https://www.liveleak.com/c/Forestdo98 https://esia.gosuslugi.ru/profile/user/settings https://nolamotor.com/NOLAforum/member.php?action=profile&uid=23055 https://www.apsense.com/user/forestdo98 https://downtownmiami.com/account/profile http://forums.qrecall.com/user/edit/46619.page http://wkhelp.4next.ch/Main/ForestDo https://davehakkens.nl/community/members/forestdo98/ http://uid.me/forest_do http://lazienkiportal.pl/forum/member.php?action=profile&uid=186444 https://fishsniffer.com/forums/member.php?u=48152 https://slides.com/forestdo98 http://forum.ventrilo.com/member.php?u=513947 http://nasdse.org/UserProfile/tabid/574/userId/236448/Default.aspx http://www.yemle.co/profile/forestdo98 https://www.roleplaygateway.com/member/forestdo98/ https://www.bagtheweb.com/u/Forestdo98/profile https://www.screencast.com/users/forestdo98/ https://bandcamp.com/forestdo98 https://hearthis.at/forestdo98/ https://www.hashatit.com/forestdo98 http://teamfragdown.com/profile/forestdo98 http://www.rohitab.com/discuss/user/82637-forestdo98/ https://www.flipsnack.com/E6FDEC6D75E/ https://www.metal-archives.com/users/forestdo98 http://foorumi.turunsrk.fi/user/edit/3201.page http://www.letempledelaforme.com/profile/forestdo98 https://www.twitch.tv/settings/profile http://asmetalwork.1gb.ua/forum/user/editDone/19673.page https://www.mkzforum.com/forum/members/ic9cube.com.html https://anobii.com/014763464297a7c4ca/profile https://bbpress.org/forums/profile/forestdo98/ http://fifavn.org/forum/members/18699/ https://www.mobypicture.com/user/forestdo98 http://forum.aekatowice.pl/usercp.php?action=profile https://orcid.org/0000-0003-0588-8208 https://dzone.com/users/3852925/forestdo98.html https://www.dpreview.com/members/7426701322/overview https://forums.asp.net/members/forestdo98.aspx https://express.yudu.com/profile/index https://www.picdove.net/forestdo98 https://www.coursera.org/user/7a53fc17e4017a768c51e86deafe4150 https://www.minecraftforum.net/members/forestdo98 https://www.vingle.net/forestdo https://buddypress.org/members/forestdo98/profile/ https://www.udemy.com/user/forest-do/ https://www.budu.com/Forestdo98 https://www.crokes.com/forestdo98/profile/ https://itsmyurls.com/forestdo98 http://forums.carreview.com/member.php?360830-Forestdo98 https://moz.com/community/users/13480793 http://www.laborlawtalk.com/member/774605-forestdo98/about https://www.4shared.com/u/TNS9UEKx/forestdo98.html https://www.openstreetmap.org/user/Forest%20Do https://trackandfieldnews.com/discussion/member.php?269480-Forestdo98 https://www.liketly.com/Forestdo98/info/ http://www.techrum.vn/members/forestdo98.86720/#about https://www.3dbuzz.com/forum/profile.php?do=editprofile http://talkstats.com/members/forestdo98.123232/#about https://qiita.com/Forestdo98 https://www.amazon.com/gp/profile/amzn1.account.AGQDSGOANYXTWHSAUKHWH3X7K6CA?preview=true&ref=uepas https://chatroll.com/profile/Forestdo98 http://forums.stickpage.com/member.php?326958-Forestdo98 http://forum.bacsi.com/members/199563.html http://buildwpyourself.com/support/users/forestdo98/ https://www.1doi1.com/members/forestdo98.13531/ https://forum.avscripts.net/member.php?98907-Forestdo98 http://www.imfaceplate.com/forestdo98 http://forum.lemaker.org/home.php?mod=space&uid=101504&do=profile http://www.droidxforums.com/forum/members/129565.html https://www.asingularcreation.com/Forums/memberlist.php?mode=viewprofile&u=31331 http://hawkee.com/profile/681372/ https://www.evernote.com/secure/ProfileSettings.action https://www.diigo.com/user/forestdo98/b/520916386 http://molbiol.ru/forums/index.php?showuser=1143254 https://www.fifa-infinity.com/forums/member.php?u=15418 https://www.aeriagames.com/user/forestdo98/ http://www.magcloud.com/user/forestdo98 https://en.calameo.com/account/info_account http://www.unicyclist.com/forums/member.php?u=175024 http://www.wiichat.com/members/forestdo98.96090/ https://www.gpforums.co.nz/members/468754-Forestdo98 https://scioly.org/forums/memberlist.php?mode=viewprofile&u=52948 https://forum.singaporeexpats.com/memberlist.php?mode=viewprofile&u=244893 https://www.tt-forums.net/memberlist.php?modea=viewprofile&u=106911 https://www.thehackersparadise.com/forum/member/54127-forestdo98 https://linkhay.com/u/forestdo98 https://evermotion.org/vbulletin/member.php?932904 http://www.bakespace.com/members/profile/forestdo98/769399/
Hashtag: #eyeskady, #mug, #gift
1 note · View note
siliconwebx · 5 years
Text
Pipdig Updates P3 Plugin after Reports Expose Vendor Backdoors, Built-in Kill Switch, and Malicious DDoS Code
Over the weekend, Pipdig, a small commercial theme company, has been at the center of a scandal after multiple reports exposed a litany of unethical code additions to its Pipdig Power Pack (P3) plugin.
On Friday, March 29, Wordfence threat analyst Mikey Veenstra published a report with code examples of the backdoors Pipdig built into their plugin, along with some unsavory and questionable additions to the code.
“We have confirmed that the plugin, Pipdig Power Pack (or P3), contains code which has been obfuscated with misleading variable names, function names, and comments in order to hide these capabilities,” Veenstra said.
These include an unauthenticated password reset to a hard-coded string, which was deliberately obscured with code comments indicating it was added to “check for new social channels to add to navbar.” Veenstra also demonstrated how the plugin contained code for an unauthenticated database deletion, wherein the Pipdig team could remotely destroy any site WordPress site using the P3 plugin.
The code for remote site deletion was removed in version 4.8.0 but it still a concern for users who haven’t updated. Michael Waterfall, iOS Engineer at ASOS, tested the “kill switch” function and demonstrated that it still works with prior versions.
It also confirms they lied. They _still_ have the ability to wipe any blog that hasn't updated to the new plugin version (4.8.0), which they hurriedly released to delete the kill switch after they were exposed the other day. pic.twitter.com/bNMfRQUBpr
— Michael Waterfall (@mwaterfall) March 31, 2019
Veenstra’s investigation also uncovered questionable remote calls in the plugin’s cron events, undisclosed content and configuration rewrites, and a list of popular plugins that are immediately deactivated when P3 is activated, without the user’s knowledge. He found that some of these plugins are deactivated alongside admin_init, so any user attempts to reactivate the plugins will not stick.
Wordfence estimates the P3 plugin to have an install base of 10,000-15,000 sites. The changes made in version 4.8.0 of the plugin are not transparently identified in the changelog, so it’s not easy for users to know what has changed. The content filtering and the plugin deactivations remain in the most recent release. These types of veiled functions performed without permission could have unintended consequences on sites using the plugin, which non-technical users may not be able to fix themselves.
Pipdig P3 Plugin Performed a DDoS Attack on a Competitor’s Site
Jem Turner, a freelance web developer based in the UK, published a lengthy analysis of the P3 plugin the same day that Wordfence released its analysis. She drilled down further into the remote requests, demonstrating how Pipdig has been using the P3 plugin to perform a DDoS attack on a competitor who also provides WordPress themes and installation services to bloggers. The code triggers an hourly cron job on users’ sites, effectively using their customers’ servers to send malicious requests to the competitor’s site.
The code comment tells us this is “checking the CDN (content delivery network) cache”. It’s not. This is performing a GET request on a file (id39dqm3c0_license_h.txt) sat on pipdigz.co.uk, which yesterday morning returned ‘https://kotrynabassdesign.com/wp-admin/admin-ajax.php’ in the response body.
Every single hour night and day, without any manual intervention, any blogger running the pipdig plugin will send a request with a faked User Agent to ‘https://kotrynabassdesign.com/wp-admin/admin-ajax.php’ with a random number string attached. This is effectively performing a small scale DDoS (Distributed Denial of Service) on kotrynabassdesign.com’s server.
Turner also contacted Kotryna Bass, Pipdig’s competitor, who said she had contacted her host after finding that her admin-ajax.php file was under some kind of attack. Bass’ exchanges with her host are also published in Turner’s report.
Turner’s post explained how Pipdig’s P3 plugin code manipulated links to point to their own products and services when a user includes a link to a competitor in the the content:
Here we have pipdig’s plugin searching for mentions of ‘blogerize.com‘ with the string split in two and rejoined – concatenated – to make it harder to find mentions of competitors when doing a mass ‘Find in Files’ across the plugin (amongst other things). When the plugin finds links to blogerize.com in blogger’s content (posts, pages), they’re swapped out with a link to ‘pipdig.co/shop/blogger-to-wordpress-migration/’ i.e. pipdig’s own blog migration services. Swapping these links out boost the SEO benefit to pipdig, and the vast majority of bloggers wouldn’t notice the switcheroo (especially as if the page/post was edited, the link to blogerize would appear in the backend as normal).
The plugin did not ask users’ permission before performing any of these actions and most of them were implemented with obfuscated code. Turner’s investigation also covers how the P3 plugin could harvest data and change admin passwords. Many of the findings overlap with Wordfence’s analysis.
“I was aware that Wordfence had been contacted for an opinion, although I was unaware they were writing a post and vice versa,” Turner said. “I wasn’t surprised that they wrote about it though, given the risk to WordPress users.”
She has been in contact with authorities regarding Pipdig’s unethical coding practices and privacy violations.
“From my side of things, I’ve been in contact with Action Fraud (submitted a report through their website) and NCSC (who pointed me back to Action Fraud and gave me a number to call). From pipdig’s side, there are threats of legal action in their blog post but I’ve received nothing yet.”
Pipdig’s Public Response Skirts Critical Concerns
Pipdig Creative Director Phil Clothier published a public response from the company which opens by characterizing the recent investigations as “various accusations and rumours spreading about pipdig” and includes an emotional plea regarding how distressing recent developments have been for his company. He claims that his team and their supporters are being harassed.
After pushing out the 4.8.0 version of the P3 plugin, removing some but not all of the offensive code, Clothier opts for a Q&A style format for his post, putting every question in the present tense:
Do you DDOS competitors? No.
Do you “kill” sites? No!
Do you have the ability to kill sites via the pipdig Power Pack? No
Regarding the “kill switch” feature they built in, which detects all tables with the WordPress prefix and drops each of them, Clothier said it was simply a function to reset a site back to its default settings. He deliberately misrepresented what it does:
There was function in an older version of the plugin which could be used to reset a site back to the default settings. This function had no risk of of malicious or unintentional use. I can say categorically that there was no risk to your site if you were using a pipdig theme. This feature has been dug up and labelled a “Kill Switch” for maximum negative impact on us.
Clothier claims the function was available in the P3 plugin in July 2018 when a third party started posting Pipdig themes for sale on their own site:
A 3rd party was able to download all of our themes illegitimately and post them on a clone of our own site. This included previews of our themes and the ability to purchase them. We were first alerted to this by people which had purchased a pipdig theme from there, but were finding that certain features did not work correctly. After investigation, we found that the victim had purchased the theme from the 3rd party, thinking it was us. The 3rd party not only gained the financial benefit of the theme payment, but also used it as a way to inject malware and ads into the victim’s site. The reset function was put in place in order to remove the 3rd party’s ability to host preview sites with our themes. It worked, and they have since disappeared. The function was then removed in a later version of the plugin.
This is a false claim, as Wordfence pointed out in an updated article. The first instance of the code responsible for database deletion was committed to the plugin in November 2017.
The company failed to address the most critical concerns presented in the Wordfence analysis in its first pass at issuing a public statement. Instead, on the matter of coordinating a DDoS attack on competitors, Pipdig blames users and suggests they may have added the competitor’s URL to their sites.
“We’re now looking into why this function is returning this url,” Clothier said. “However, it seems to suggest that some of the ‘Author URLs’ have been set to ‘kotrynabassdesign.com’. We don’t currently know why this is the case, or whether the site owner has intentionally changed this.”
Further investigations published by Wordfence today showed that Pipdig also added DDoS code to its Blogger templates and was actively issuing malicious requests up until yesterday:
During the investigation of Pipdig’s WordPress plugin and themes, we also came across some curious code associated with their Blogger themes. This code is part of Pipdig’s suspected DDoS campaign against their competitor, and was active until April 1, four days after Pipdig’s denial of any such behavior.
Some of Pipdig’s Blogger themes have been confirmed to make external JavaScript calls to Pipdig’s server, specifically to the script hXXps://pipdigz[.]co[.]uk/js/zeplin1.js.
On March 31, as the investigations became public, Pipdig deleted its public Bitbucket repository and replaced it with a “clean one,” removing three years of commit history. Wordfence and many others cloned the repository before it was deleted and saved snapshots of pages to cite in the investigation.
That clean repository @pipdig published earlier today in place of the one containing all of their malicious code… They changed the reported release date of version 4.8.0. pic.twitter.com/YqKASTUZE7
— Nicky Bloor (@nickstadb) April 1, 2019
Pipdig’s public statement contains a number of other false claims that are outlined in Wordfence’s followup piece with code examples. Clothier closes the article by casting aspersion on the press, presumably to encourage customers not to trust what they read from other sources.
I contacted Pipdig for their comment on recent events, but Clothier declined to answer any of my questions. One of those was why the plugin disables Bluehost’s caching plugin without informing customers.
Another one from the @pipdig plugin. If you use one of their themes on @bluehost then they intentionally slow your website down by disabling the BlueHost cache plugin, then they can inject content with the title "Is your host slowing you down?" CC @jemjabella @heyitsmikeyv pic.twitter.com/48DUXsDyBj
— Nicky Bloor (@nickstadb) March 31, 2019
Clothier said he didn’t have any comments beyond what he said in the public statement but encouraged anyone interested to read the new comments added to the code in version 4.9.0:
We’ve also updated version 4.9.0 of the plugin which includes extra commenting in the code, which will hopefully help clear things up like issues with Bluehost caching and the_content() filter.
If anyone is unsure, we recommend updating to the latest version as always. However we also contend that the previous versions had no serious issues too.
Pipdig declined to answer questions about licensing but the products do not appear to be GPL-licensed. This may be why the company deemed it within its rights to take action on those who they believe to have “stolen” their themes.
Pipdig Customers Share Mixed Reactions to Reports of Vendor Backdoors and DDoS Attacks
In what is perhaps one of the most brazen abuses I’ve ever seen from a theme company in WordPress’ history, Pipdig’s user base has unknowingly been used to target the company’s competitors. Regardless of the company’s motive in combatting the unauthorized distribution of their themes, these types of backdoors and undisclosed content rewrites are indefensible. They prey upon user trust and in this case the victims were primarily bloggers.
I think that's why so many of us are so angry. Bloggers are the lifeblood of #WordPress, you create content and for the most part don't have big budgets to spend. So when someone takes advantage of that those at the "low budget" end of the market, those that cant afford devs…
— Andy Powell (@p0welly) March 31, 2019
One of the more puzzling aspects of this story is that many of Pipdig’s users seem to be unfazed by the gravity of the findings in these reports. Without full knowledge of the inner workings of a product, many customers make decisions based on how they feel about a company, regardless of being confronted with facts that should cause them to question their experiences.
I’m not concerned. I trust them. And I’m certainly not panicking and acting on the words of two blog posts citing their competitors. They’ve served me well for years.
— Caroline Hirons (@CarolineHirons) March 29, 2019
Others are angry to have had their sites used in an attack. Getting set up on a new theme is not a trivial task for non-technical users who may have had to pay a developer to launch their sites in the first place.
Honestly? I’m really angry. I trusted them for years, and in return my site has been used maliciously against other small businesses. I’ve been watching this unfold since Friday but even this update shocked me. https://t.co/mPsO8EoHBp
— Charlotte (@bycharlotteann_) April 2, 2019
“My mind is absolutely blown by pipdig’s public response,” Jem Turner said. “I understand that they were counting on their users’ completely non-tech background to bamboozle them, and it certainly seemed to be working in the beginning, but anyone with even the slightest bit of coding knowledge can see that they are lying and I genuinely don’t understand how they think they’ll get away with it.”
The crazy part is if we want to be really real about this, it's more like
The cable guy cut a big hole in my wall and installed a door handle on it. He took some painter's tape and scrawled "THIS IS A CABLE BOX" on the drywall. Then looked me in the eyes and said "No I didn't."
— Mikey Veenstra (@heyitsmikeyv) March 31, 2019
This incident shines a spotlight on how unregulated the commercial plugin and theme ecosystem is and how little protection users have from companies that abuse their power. If you are a Pipdig customer affected by this incident, there is no assurance that the company will not build more backdoors into your site in the future. The plugin updates are not reviewed by any kind of authority. Fortunately, there are a few actions you can take to create a safer environment for your website.
First, look for GPL-licensed themes and plugins, because they grant you more freedoms as the user and are compatible with WordPress’ legal license. GPL-licensed products are also a strong indication that the authors respect user freedoms and the shared economic principles that this open source license supports.
Many reputable theme companies choose to host their products’ companion plugins on WordPress.org for ease of distribution and shipping updates. The official directory does not permit these kinds of shady coding practices described in this article and all of the plugins go through a security review by the WordPress Plugin Team. If you are concerned about code quality and the potential for abuse, do a little research on your next prospective commercial theme provider or opt for free WordPress.org-hosted themes and plugins that have undergone a more rigorous vetting process.
😉SiliconWebX | 🌐WPTavern
1 note · View note
security · 6 years
Text
Tumblr's 4th Annual Security Capture the Flag
We've hosted an internal Security Capture the Flag (CTF) event for four years in a row now, with each year getting better than the last!
The event
Previously, we were only open to Tumblr employees. This year we decided to extend an invite out to the other teams housed under our parent company, Oath.
All participants had a three hour window to hack, a buffet of tacos, beer, and wine to dive into, and a stack of prizes for the top four players (see Prizes below for details)!
Challenges were available Jeopardy-style, broken down by category. We had eight fun categories to select from:
Auth Bypass (authn | authz)
Cross Site Request Forgery (CSRF)
Cross Site Scripting (XSS)
Crypto
Forensics
Reverse Engineering
SQL Injection (SQLi)
XML Injection (+ XXE)
We also sprinkled a few "inside joke" Easter eggs around the system that awarded bonus points to anyone that discovered them! For example, if they attempted to find a hole in the CTF system itself and navigated to /wp-admin, we'd give them a flag on a prank WordPress page; or perhaps testing to find XSS with a <marquee> tag — only the greatest of all XSS tags!
While the Security Team walked around and helped out, we also setup a mini lockpick village just because.
Solving challenges & scoring points
To complete a challenge, the player had to achieve the goal within one of the listed categories.
In XSS challenges, the player would need to cause the browser to create an alert dialog (e.g. alert()).
Conversely, in SQL Injection challenges the player would need to read the flag column from the flags table in that challenge's database.
When the player successfully solved the challenge they were awarded with a flag, each in the format ofTumblr{s0mE_cHalL3nGe_j0kE-abcdef012}. That last piece is a unique hash for the user, per challenge, so that they couldn't directly share their flag. They can help others — even provide the solution — but they can't simply give away their flag.
Each challenge, when solved, is worth a certain number of points based on the challenge's difficulty and whether or not the player used the challenge's hints.
There were 3800 points available, though no player was able to break 1000!
At the end, we locked the leaderboard and announced the winners.
Prizes
We awarded the top four players based on their ranking on the leaderboard. First place got first dibs from the list. Second place gets to select theirs from the remaining lot, and so on.
Up for grabs this year:
Hak5 Elite Field Kit
Proxmark3 RDV2 Kit
Samsung Chromebook Plus
Lockpick set and a "how to" manual
Challenge snapshot
Throughout the eight categories we had a total of 46 challenges. We wanted to have a wide range of challenges that welcomed players of all backgrounds and experience levels.
The goal for XSS challenges was to get an alert dialog to appear. The player is presented with a vulnerable web page and they needed to determine where the vulnerability is and how to exploit it. Example:
Tumblr media
These challenge levels ranged everywhere between simple non-sanitized output to DOM reflection to CSP bypasses.
One fo the more unique challenges to develop was SQL Injection. These offered players the ability to put their SQL skills to the test with a variety of basic input injection, blind injection, and filter bypassing challenges.
Tumblr media
In at least one of the SQLi challenges, players had to inject into an INSERT statement. When creating challenges like this, special care had to be taken to give players the full capabilities of MySQL but also prevent them from revealing the flag to other players — it's a tricky thing making vulnerabilities secure!
The infrastructure
A frequent question I receive when I talk about deving on the CTF is "are you using CTFd?" Short answer? Nope! A slightly less short answer is that CTFd wasn't out when we started this =P.
The framework we're using is called "Security Training Grounds" and it's a custom-written project using PHP, PhantomJS, and MySQL (with HTML + JavaScript too, of course), running in Amazon Web Services.
An advantage of writing this in-house was that it gave us the ability to create a dynamic and robust system that has endless capabilities.
PHP + MySQL
The website was created from scratch, written in PHP with a little bit of jQuery + Bootstrap on the frontend and MySQL as the database.
The big thing here are the challenges themselves. Each challenge is hosted on its own subdomain. This enables us to provide live and interactive challenges like XSS or SQLi while still providing support static challenge types like Crypto or Reverse Engineering.
We accomplished this by allowing dynamic hostnames on the webserver and defining a subdomain hostname for each challenge that's stored in MySQL. When a web request comes in, the app checks whether it's a subdomain or not. If so, it hits the database to determine what to display.
For most challenges, we were able to handle all of the dynamic pieces directly in PHP. For some, such as the C or Java reverse engineering challenges, we did need to shell out to gcc or javac to build the custom binaries for each user.
PhantomJS
A difficulty for XSS and CSRF challenges is determining whether or not the participant successfully exploited the system. Surely we don't want to manually confirm for each flag, and attempting to pattern-match on their input would be crazy.
Our solution: execute what the player submits!
This is my own little baby, a piece of the system I'm so excited by. See, what better way to test XSS than to actually test XSS. As mentioned in the "Challenge snapshot" section above, when a player is working on a XSS challenge, they are given a website that has a XSS vulnerability. Their goal is to make an alert dialog appear. This is key and the requirement of the XSS framework itself.
On the client, we use this fancy little snippet:
var ctf_alert = alert; alert = function(msg) {    ctf_phantomjs_alert_test(document.location, msg); };
This overrides the window's actual alert() function and lets us put some processing logic in the middle. The logic is to take a snapshot of the current page - the URL, query string, POST parameters, the cookies and then pass the full snapshot to a backend PhantomJS service (via a PHP proxy, to help prevent tampering).
The PhantomJS service replicates that entire request and loads the target web page. If the page invokes an alert() call, which we catch via PhantomJS's onAlert, then we return with a "success" and the PHP proxy will return the user's flag. Our alert() overriding logic will then replace whatever message the user attempted to display and display their flag instead. Fancy af.
CSRF has a similar setup, except the player needs to submit their full CSRF payload:
Tumblr media
After submitting the payload to the PHP proxy, we pass the payload to PhantomJS. This executes the payload in the context of an empty web page. If the PhantomJS worker successfully falls victim to the targeted action, the PHP proxy will return a flag to the user!
Open source
The framework code, as-is, is still relatively hacky and written with internal dependencies. We do believe in OSS though! We expect a near-future initiative to rewrite portions of it so we can release it for others to use for their CTF events, too.
Wanna Play?
Quick, come apply so you can participate in the next one: https://www.tumblr.com/jobs
115 notes · View notes